If a page has dynamic routes
(documentation) and uses
getStaticProps
it needs to define a list of paths that have to be
rendered to HTML at build time.
If you export an async
function called getStaticPaths
from a page that
uses dynamic routes, Blitz will statically pre-render all the paths
specified by getStaticPaths
.
export async function getStaticPaths() {
return {
paths: [
{ params: { ... } } // See the "paths" section below
],
fallback: true or false // See the "fallback" section below
};
}
paths
key (required)The paths
key determines which paths will be pre-rendered. For example,
suppose that you have a page that uses dynamic routes named
app/posts/pages/posts/[id].js
. If you export getStaticPaths
from this
page and return the following for paths
:
return {
paths: [
{ params: { id: '1' } },
{ params: { id: '2' } }
],
fallback: ...
}
Then Blitz will statically generate posts/1
and posts/2
at build time
using the page component in app/posts/pages/posts/[id].js
.
Note that the value for each params
must match the parameters used in
the page name:
app/posts/pages/posts/[postId]/[commentId]
, then
params
should contain postId
and commentId
.pages/[...slug]
,
then params
should contain slug
which is an array. For example, if
this array is ['foo', 'bar']
, then Blitz will statically generate the
page at /foo/bar
.null
, []
,
undefined
or false
to render the root-most route. For example, if
you supply slug: false
for pages/[[...slug]]
, Blitz will statically
generate the page /
.fallback
key (required)The object returned by getStaticPaths
must contain a boolean fallback
key.
fallback: false
If fallback
is false
, then any paths not returned by getStaticPaths
will result in a 404 page. You can do this if you have a small number
of paths to pre-render - so they are all statically generated during build
time. It’s also useful when the new pages are not added often. If you add
more items to the data source and need to render the new pages, you’d need
to run the build again.
Here’s an example which pre-renders one blog post per page called
app/posts/pages/posts/[id].js
. The list of blog posts will be fetched
from your database or a CMS and returned by getStaticPaths
. Then, for
each page, it fetches the data for a single post using getStaticProps
.
// app/posts/pages/posts/[id].js
function Post({post}) {
// Render post...
}
// This function gets called during pre-rendering
export async function getStaticPaths() {
// 1. Use a blitz query to get all posts
// 2. Or call an external API endpoint to get posts
const posts = /* ... */
// Get the paths we want to pre-render based on posts
const paths = posts.map((post) => ({
params: {id: post.id},
}))
// We'll pre-render only these paths at build time.
// { fallback: false } means other routes should 404.
return {paths, fallback: false}
}
// This also gets called at build time
export async function getStaticProps({params}) {
// params contains the post `id`.
// If the route is like /posts/1, then params.id is 1
const post = /* get one post */
// Pass post data to the page via props
return {props: {post}}
}
export default Post
fallback: true
If fallback
is true
, then the behavior of getStaticProps
changes:
getStaticPaths
will be rendered to HTML at
build time.getStaticProps
.In the “fallback” version of a page:
router.isFallback
will be true
.Here’s an example that uses isFallback
:
// app/posts/pages/posts/[id].js
import {useRouter} from "blitz"
function Post({post}) {
const router = useRouter()
// If the page is not yet generated, this will be displayed
// initially until getStaticProps() finishes running
if (router.isFallback) {
return <div>Loading...</div>
}
// Render post...
}
// This function gets called at build time
export async function getStaticPaths() {
return {
// Only `/posts/1` and `/posts/2` are generated at build time
paths: [{params: {id: "1"}}, {params: {id: "2"}}],
// Enable statically generating additional pages
// For example: `/posts/3`
fallback: true,
}
}
// This also gets called at build time
export async function getStaticProps({params}) {
// params contains the post `id`.
// If the route is like /posts/1, then params.id is 1
const post = /* ... */
// Pass post data to the page via props
return {props: {post}}
}
export default Post
fallback: true
useful?fallback: true
is useful if your app has a very large number of static
pages that depend on data (think: a very large e-commerce site). You want
to pre-render all product pages, but then your builds would take forever.
Instead, you may statically generate a small subset of pages and use
fallback: true
for the rest. When someone requests a page that’s not
generated yet, the user will see the page with a loading indicator.
Shortly after, getStaticProps
finishes and the page will be rendered
with the requested data. From now on, everyone who requests the same page
will get the statically pre-rendered page.
This ensures that users always have a fast experience while preserving fast builds and the benefits of Static Generation.
fallback: true
will not update generated pages, for that take a look
at
Incremental Static Regeneration.
fallback: 'blocking'
If fallback
is 'blocking'
, new paths not returned by getStaticPaths
will wait for the HTML to be generated, identical to SSR (hence why
blocking), and then be cached for future requests so it only happens
once per path.
getStaticProps
will behave as follows:
getStaticPaths
will be rendered to HTML at
build time by getStaticProps
.fallback: 'blocking'
will not update generated pages by default. To
update generated pages, use
Incremental Static Regeneration
in conjunction with fallback: 'blocking'
.
getStaticPaths
?You should use getStaticPaths
if you’re statically pre-rendering pages
that use dynamic routes.
GetStaticPaths
For TypeScript, you can use the GetStaticPaths
type from blitz
:
import { GetStaticPaths } from "blitz"
export const getStaticPaths: GetStaticPaths = async () => {
// ...
}
getStaticProps
When you use getStaticProps
on a page with dynamic route parameters, you
must use getStaticPaths
.
You cannot use getStaticPaths
with getServerSideProps
.
getStaticPaths
only runs at build time on server-side.
getStaticPaths
can only be exported from a page. You can’t export it
from non-page files.
Also, you must use export async function getStaticPaths() {}
— it will
not work if you add getStaticPaths
as a property of the page
component.
In development (blitz dev
), getStaticPaths
will be called on every
request.