patterntypescriptnextjsModerate
generateStaticParams: pre-generating dynamic routes at build time
Viewed 0 times
Next.js 13+ App Router (replaces getStaticPaths)
generateStaticParamsgetStaticPathsstatic generationdynamic routesdynamicParamsbuild time
Problem
Dynamic routes like /blog/[slug] are server-rendered on every request by default. High-traffic pages should be statically generated at build time for performance, but the old getStaticPaths API doesn't exist in App Router.
Solution
Export generateStaticParams from any dynamic segment page:
// app/blog/[slug]/page.tsx
export async function generateStaticParams() {
const posts = await fetch('https://cms.example.com/posts').then(r => r.json());
return posts.map((post: { slug: string }) => ({ slug: post.slug }));
// Returns: [{ slug: 'hello-world' }, { slug: 'second-post' }, ...]
}
export default async function BlogPost({ params }) {
const { slug } = await params;
const post = await fetchPost(slug);
return <Article post={post} />;
}
// Control behavior for params not in generateStaticParams:
export const dynamicParams = true; // generate on-demand (default)
export const dynamicParams = false; // return 404 for unknown params
// For nested dynamic routes — app/[category]/[slug]/page.tsx:
export async function generateStaticParams() {
const posts = await fetchAllPosts();
return posts.map(post => ({
category: post.category,
slug: post.slug,
}));
}
// app/blog/[slug]/page.tsx
export async function generateStaticParams() {
const posts = await fetch('https://cms.example.com/posts').then(r => r.json());
return posts.map((post: { slug: string }) => ({ slug: post.slug }));
// Returns: [{ slug: 'hello-world' }, { slug: 'second-post' }, ...]
}
export default async function BlogPost({ params }) {
const { slug } = await params;
const post = await fetchPost(slug);
return <Article post={post} />;
}
// Control behavior for params not in generateStaticParams:
export const dynamicParams = true; // generate on-demand (default)
export const dynamicParams = false; // return 404 for unknown params
// For nested dynamic routes — app/[category]/[slug]/page.tsx:
export async function generateStaticParams() {
const posts = await fetchAllPosts();
return posts.map(post => ({
category: post.category,
slug: post.slug,
}));
}
Why
generateStaticParams replaces getStaticPaths from Pages Router. It runs at build time to generate the list of dynamic param combinations to pre-render as static HTML. Pre-rendered pages are served from CDN with zero server computation per request.
Gotchas
- generateStaticParams has access to the build-time environment — fetch calls are cached and deduplicated
- Setting dynamicParams = false causes unknown slugs to 404 at request time (no on-demand generation)
- For parent layouts with dynamic segments, generateStaticParams can narrow the list for child pages
- In development (next dev), generateStaticParams is not called — pages are always server-rendered
Code Snippets
generateStaticParams with strict mode
export async function generateStaticParams() {
const products = await db.product.findMany({ select: { slug: true } });
return products.map(p => ({ slug: p.slug }));
}
export const dynamicParams = false;Context
When pre-generating dynamic route pages at build time for performance in Next.js App Router
Revisions (0)
No revisions yet.