Building Pages
How to build pages using JSON:API resources from Drupal.
In Next.js, you fetch server-side data in either getStaticProps
or getServerSideProps
. Data is then fed to your pages for pre-rendering.
The DrupalClient
provides several functions to help you query JSON:API resources from Drupal.
Basic Example
Here's an example which uses getResource
to fetch a page
node by ID:
const node = await drupal.getResource( "node--page", "07464e9f-9221-4a4f-b7f2-01389408e6c8")
A full page would look like this:
pages/about.tsx
// node will be populated at build time by getStaticPropsexport default function AboutPage({ node }) { return ( <article> <h1>{node.title}</h1> // ... </article> )}
export async function getStaticProps() { // Fetch the node from Drupal. const node = await drupal.getResource( "node--page", "07464e9f-9221-4a4f-b7f2-01389408e6c8" )
// Pass the node as props to the AboutPage. return { props: { node, }, }}
Dynamic pages
You can use Next.js dynamic route to build static pages for Drupal entity types.
Start by creating a page at /pages/[...slug].tsx
, where [...slug]
maps to the path alias for an entity type (or content type) in Drupal.
This means /pages/[...slug].tsx
will handle all pages with the following aliases: /about
, /team
, /another/path
...etc.
To build static pages, there are two functions we need to implement:
getStaticPaths
: to tell Next.js all the routes that we want to be rendered.getStaticProps
: to fetch data for pages.
pages/[...slug].tsx
export default function Page({ node }) { return ( <article> <h1>{node.title}</h1> // ... </article> )}
export async function getStaticPaths(context) { // Build paths for all `node--page`. return { paths: await drupal.getStaticPathsFromContext("node--page", context), fallback: false, }}
export async function getStaticProps(context) { // Fetch the node based on the context. // next-drupal automatically handles the slug value. const node = await drupal.getResourceFromContext("node--page", context)
return { props: { node, }, }}
Advanced Example
In the example above, we used pages/[...slug].tsx
to build static pages for node--page
.
We can go a step further and handle all node types (or any entity types) in one page.
To do that, we're going to use translatePathFromContext
which returns info about the resource type based on slug
value in context
.
export async function getStaticProps(context) { const path = await drupal.translatePathFromContext(context)
// Get the resource type. const type = path.jsonapi.resourceName
if (type === "node--article") { // Build custom JSON:API query for article. }
if (type === "node--page") { // Build custom JSON:API query for page. }}
Let's update pages/[...slug].tsx
to handle both node--page
and node--article
.
pages/[...slug].tsx
import { DrupalJsonApiParams } from "drupal-jsonapi-params"
export default function Page({ node }) { if (node.type === "node--page") { return <PageComponent /> }
if (node.type === "node--article") { return <ArticleComponent /> }
return null}
export async function getStaticPaths(context) { // Build paths for all `node--page` and `node--article`. return { paths: await drupal.getStaticPathsFromContext( ["node--page", "node--article"], context ), fallback: false, }}
export async function getStaticProps(context) { const path = await drupal.translatePathFromContext(context)
// Get the resource type. const type = path.jsonapi.resourceName
const params = new DrupalJsonApiParams()
// Fetch the title, path and body field for pages. if (type === "node--page") { params.addFields("node--page", ["title", "path", "body"]) }
// Fetch additional fields for articles. if (type === "node--article") { params.addFields("node--article", ["title", "path", "body", "uid"]) }
const node = await drupal.getResourceFromContext(type, context, { params: params.getQueryObject(), })
return { props: { node, }, }}
Reference
See the fetching JSON:API resources section for more examples of fetching resources and collection of resources.