Next.js
5. SSR, SSG, ISR and generateStaticParams
SSR, SSG, and ISR are not three isolated mechanisms in the App Router; rather, they represent different combinations of `fetch()` cache options (covered in the previous section) alongside `generateStaticParams()` and `dynamicParams`.
On this page
Context
In the legacy Pages Router, the 3 rendering strategies mapped to 3 distinct functions (getServerSideProps, getStaticProps, getStaticProps + revalidate). The App Router unifies them into a single coherent model driven by fetch() configurations, which can cause confusion if not properly connected to caching concepts.
Strategy Definitions
- SSR (Server-Side Rendering): HTML is rendered on the server on every incoming request, always fetching the freshest data available at that moment. The trade-off is higher latency (each request incurs server render time + data fetching overhead).
- SSG (Static Site Generation): HTML is pre-rendered a single time at build time (
npm run build) and stored as static files. All subsequent users receive that exact same static HTML, making delivery extremely fast (zero runtime re-rendering, zero per-request data fetching), but data remains frozen until the next deployment. - ISR (Incremental Static Regeneration): combines the strengths of both—delivers static HTML as fast as SSG, but automatically revalidates periodically (time-based, or on-demand) without rebuilding the entire application.
2. SSG requires generateStaticParams() to declare parameters
- SSG: HTML is pre-generated at build time (
npm run build), and every user receives the exact same static HTML file. - Next.js cannot know automatically which dynamic params to pre-build (e.g. the list of product
ids); they must be explicitly declared viagenerateStaticParams():
tsx
export async function generateStaticParams() {
const products = await db.product.findMany({ select: { id: true } });
return products.map(p => ({ id: p.id.toString() }));
}
- Avoid listing the entirety of a massive dataset (e.g. 10,000 products) in
generateStaticParams(), as Next.js would have to render all 10,000 pages during build time, dramatically inflating build durations.
3. dynamicParams: handling un-pre-built params (on-demand ISR)
- Pre-generate only a subset in
generateStaticParams()(e.g. the top 100 best-selling products):
tsx
export const dynamicParams = true; // default
export async function generateStaticParams() {
const topProducts = await db.product.findMany({ take: 100, orderBy: { sales: 'desc' } });
return topProducts.map(p => ({ id: p.id.toString() }));
}
- With
dynamicParams = true(default), when a user requests a param not present in the pre-built list, Next.js renders it on-the-fly (similar to SSR for the first hit) and persists it as a static page for subsequent users.
4. Rendering Strategies Summary Table
| Strategy | Configuration | Render Trigger |
|---|---|---|
| SSG (Static) | Default fetch(url) (force-cache), with generateStaticParams() covering all target params | Build time, once |
| SSR (Per Request) | fetch(url, { cache: 'no-store' }) | Every incoming request, always renders fresh |
| ISR (Incremental) | fetch(url, { next: { revalidate: N } }), or SSG + dynamicParams: true for un-pre-built params | Build time (subset) + background revalidation after N seconds, or rendered on-demand on first visit then cached |
