Rendering Strategies
Next.js supports multiple rendering strategies. Choosing the right one affects performance, SEO, and freshness of your content.
Overview
| Strategy | Acronym | When HTML is generated | Best for |
|---|---|---|---|
| Static Site Generation | SSG | Build time | Blogs, docs, marketing pages |
| Server-Side Rendering | SSR | Every request | Personalized, real-time data |
| Incremental Static Regeneration | ISR | Build time + periodic refresh | Large catalogs, news feeds |
| Client-Side Rendering | CSR | In the browser | Dashboards, authenticated apps |
Static Site Generation (SSG)
Pages are pre-rendered at build time and served as static HTML.
// app/about/page.tsx — static by default
export default function AboutPage() {
return <h1>About Us</h1>;
}
Run npm run build — Next.js generates HTML files served instantly from a CDN.
Data fetching with default cache also produces static pages:
export default async function BlogPage() {
const posts = await fetch('https://api.example.com/posts').then(r => r.json());
return <PostList posts={posts} />;
}
Server-Side Rendering (SSR)
HTML is generated on every request. Use when content must be fresh or personalized.
export const dynamic = 'force-dynamic';
export default async function DashboardPage() {
const session = await getSession();
const data = await fetchUserData(session.userId, { cache: 'no-store' });
return <Dashboard data={data} />;
}
Triggers for dynamic rendering:
export const dynamic = 'force-dynamic'fetch(..., { cache: 'no-store' })- Using
cookies()orheaders()fromnext/headers
Incremental Static Regeneration (ISR)
Static pages that automatically refresh after a time interval:
export const revalidate = 60; // Regenerate at most every 60 seconds
export default async function ProductsPage() {
const products = await fetch('https://api.example.com/products').then(r => r.json());
return <ProductGrid products={products} />;
}
How ISR works: serve cached page → after interval, next request triggers background regeneration → subsequent requests get updated content.
Client-Side Rendering (CSR)
Interactive parts render in the browser via Client Components:
'use client';
import { useEffect, useState } from 'react';
export default function LiveChart() {
const [data, setData] = useState(null);
useEffect(() => {
fetch('/api/metrics').then(r => r.json()).then(setData);
}, []);
if (!data) return <p>Loading chart...</p>;
return <Chart data={data} />;
}
Use CSR for highly interactive UI that does not need SEO.
Streaming and Suspense
Next.js streams HTML progressively. Wrap slow components in <Suspense>:
import { Suspense } from 'react';
export default function Page() {
return (
<main>
<h1>Dashboard</h1>
<Suspense fallback={<p>Loading stats...</p>}>
<SlowStatsComponent />
</Suspense>
</main>
);
}
Choosing a Strategy
Same content for all users?
├── Yes → Can it be stale for minutes/hours?
│ ├── Yes → SSG or ISR
│ └── No → SSR
└── No (personalized) → SSR or CSR for interactive parts
During npm run build, check the route table: ○ Static, λ Dynamic (SSR), ◐ ISR.
Next: build API endpoints with Route Handlers.