generateStaticParams and Incremental Static Regeneration
Pre-rendering specific dynamic routes at build time, and refreshing them later without a full redeploy.
読了時間 3 分
Dynamic segments like [slug] are, by default, rendered on demand — the first time someone requests /blog/hello-world, Next.js renders that specific page. generateStaticParams lets you tell Next.js which values of a dynamic segment to pre-render at build time instead, so those specific pages are already static HTML before a single visitor arrives.
Declaring which params to pre-render
Export an async generateStaticParams function from the same file as your dynamic page. It returns an array of objects, each shaped like the route's params:
// app/blog/[slug]/page.tsx
export async function generateStaticParams() {
const posts = await fetch("https://api.example.com/posts").then((res) =>
res.json()
);
return posts.map((post: { slug: string }) => ({
slug: post.slug,
}));
}
export default async function BlogPostPage({
params,
}: {
params: Promise<{ slug: string }>;
}) {
const { slug } = await params;
const post = await getPostBySlug(slug);
return <article>{post.title}</article>;
}During next build, Next.js calls generateStaticParams, gets back (say) 50 slugs, and renders all 50 pages to static HTML — each one as fast as the about page from the static rendering lesson, despite sharing one dynamic route file.
What happens to URLs not in the list
If a visitor requests /blog/a-post-published-after-the-last-build — a slug generateStaticParams didn't know about — Next.js doesn't 404 by default. It renders that page on demand at request time, the same as it would without generateStaticParams at all. You can change this with dynamicParams = false exported alongside it, which forces a 404 for any slug not explicitly listed — useful when you want a hard guarantee that only known content is ever served.
Incremental Static Regeneration (ISR)
Static generation solves speed, but raises an obvious question: what happens when the underlying content changes after the build? ISR is time-based revalidation applied to statically generated dynamic routes — pair generateStaticParams with a revalidate export, and Next.js will regenerate a page in the background after it goes stale, without you needing to redeploy the whole app:
export const revalidate = 3600; // regenerate at most once per hour
export async function generateStaticParams() {
const posts = await getPosts();
return posts.map((post) => ({ slug: post.slug }));
}The first visitor after an hour has passed still gets the existing (slightly stale) HTML instantly — Next.js kicks off a fresh render behind the scenes and swaps it in for the next visitor. Nobody ever waits on a slow render; they just occasionally see data that's up to an hour old.
Why bother, instead of always rendering on demand?
The performance difference is real: a pre-rendered page can be served from a CDN edge cache with no server compute involved at all, while an on-demand render still has to run your data fetching and React rendering for every single new visitor to that URL. generateStaticParams is how you get CDN-level speed for content that's mostly stable — blog posts, product pages, documentation — while still allowing it to update periodically instead of being frozen at the exact moment of the last deploy.