In Next.js, there are two forms of pre-rendering, Static Generation and Server-side Rendering. We can apply these methods for each page individually.
The Static Generation method fetches the page’s data on build-time, and
renders static HTML files. To apply the Static Generation method, we need to
export a getStaticProps
method from our page:
// pages/index.tsx
import type { GetStaticProps } from 'next'
import type { Lesson } from 'types/lesson'
import { fetchLessons } from 'utils/lessons'
type Props = {
lessons: Lesson[]
}
const Home = ({ lessons }: Props) => {
return (
<ul>
{lessons.map((lesson) => (...))}
</ul>
)
}
export const getStaticProps: GetStaticProps<Props> = async (context) => {
const lessons = await fetchLessons()
const props: Props = {
lessons
}
return {
props
}
}
export default Home
For our Home page, Next.js will execute the fetchLessons
method
asynchroniously, and pass the lessons array as a prop in our Home
component.
If there is no data for the given query, we need to return notFound: true
instead of the props. If the lessons data changes and we want to update the
page, we can either rebuild our website, or use the
Incremental Static Regeneration method.
In our getStaticProps
method we can also obtain the context
, which holds
data like:
params
: the route parameters for pages that use dynamic routespreview
: a boolean which istrue
if the page is in the Preview Mode, otherwiseundefined
previewData
: an object that holds the preview data set bysetPreviewData
locale
: the active locale, if you’ve enabled Internationalized Routinglocales
: an array that contains all of the localesdefaultLocale
: the default configured locale
Incremental Static Regeneration
The ISR method is an extension of the Static Generation method. We can enable
ISR if we provide a revalidate
property in our getStaticProps
result:
export const getStaticProps: GetStaticProps<Props> = async (context) => {
return {
props: {...},
revalidate: 60 * 60,
}
}
The revalidate
property will tell Next.js to “revalidate” our data maximum one
time in the given timeframe (in our case is 1 hour, 60 seconds times 60).
Building pages with dynamic routes
Since the Static Generation happens on build-time, if we have a page that uses
Dynamic Routes we also need to export the getStaticPaths
method. The
getStaticPaths
method returns a list of paths that have to be rendered to HTML
at build-time.
import type { GetStaticProps, GetStaticPaths } from 'next'
...
export const getStaticPaths: GetStaticPaths = async () => {
const lessons = await fetchLessons()
return {
paths: lessons.map({ slug } => ({ params: { slug } })),
fallback: false
}
}
The paths
key determines which paths will be pre-rendered. If for example we
had 3 lessons, Next.js will pre-render the following URLs:
/lessons/getting-started
/lessons/create-pages
/lessons/create-dynamic-routes
For each lesson, Next.js will execute the getStaticProps
method. That
pre-renders every page and generates static HTML files for them.
The fallback
key is a boolean key that we must include in our getStaticPaths
result. If it’s set to false
, then any paths that are not returned by the
getStaticPaths
method will result in a 404 page. If it’s set to true
,
Next.js will render a “fallback” page while it statically generates the HTML and
JSON (this includes running the getStaticProps
method). When it’s done, the
page will receive the brand new data in its props and it will render its
contents. At the end of the process, Next.js will add the new path to the list
of pre-rendered pages.
If our page supports a fallback, we can use Next.js’s router to check if Next.js wants us to render a fallback page:
import { useRouter } from 'next/router'
const Home = () => {
const router = useRouter()
if (router.isFallback) {
return <div>Loading...</div>
}
...
}
If we don’t want to display a Loading page, we can set the fallback
property
in getStaticPaths
to 'blocking'
. This will make the browser wait for Next.js
to pre-render the HTML.