- Next.js
- Next.js Rendering Foundations
- Evolution of Web Rendering: CSR, SSR, SSG, and ISR
Evolution of Web Rendering: CSR, SSR, SSG, and ISR
CSR ships a minimal HTML shell and executes JavaScript in the browser. SSR renders full HTML dynamically on every request on the server. SSG generates static HTML once at build time for instant CDN distribution, while ISR adds background regeneration using stale-while-revalidate headers without full rebuilds.
Learning Objectives
Compare performance characteristics (TTFB, FCP, LCP) across CSR, SSR, SSG, and ISR.
Explain the computational and cost trade-offs of per-request server rendering versus CDN edge caching.
Identify when to choose static generation with background revalidation over dynamic rendering.
Understand how search engine crawlers interpret client-hydrated single-page applications.
Prerequisites & Background Knowledge
Why Interviewers Care
Foundational screening question asked at nearly every tech company to gauge architectural maturity.
The Challenge
Compare and contrast CSR, SSR, SSG, and ISR. Explain the server overhead, Time to First Byte (TTFB), Largest Contentful Paint (LCP), and cache invalidation strategies for each paradigm.
Code Architecture & Implementation
1// 1. STATIC SITE GENERATION (SSG) / Default Static Prerender2// Rendered at build time. Served globally from edge CDN.3export default async function StaticMarketingPage() {4 const data = await fetch('https://api.cms.com/about', {5 // In Next.js 15+, fetch defaults to no-store unless cached explicitly6 next: { revalidate: false } // or export const dynamic = 'force-static'7 }).then(res => res.json());89 return <div>{data.headline}</div>;10}1112// 2. INCREMENTAL STATIC REGENERATION (ISR)13// Stale-while-revalidate: served from CDN cache, revalidated in background every 60s14export default async function ProductCatalogPage() {15 const products = await fetch('https://api.store.com/products', {16 next: { revalidate: 60 } // background regeneration window17 }).then(res => res.json());1819 return <ul>{products.map((p: any) => <li key={p.id}>{p.title}</li>)}</ul>;20}2122// 3. SERVER-SIDE RENDERING (SSR) / Dynamic Request-Time Rendering23// Runs on every HTTP request on Node.js / Edge server. Ideal for private/auth data.24import { cookies } from 'next/headers';2526export default async function UserDashboard() {27 const cookieStore = await cookies(); // Accessing dynamic request info triggers SSR28 const token = cookieStore.get('session')?.value;29 const user = await fetch('https://api.auth.com/me', {30 headers: { Authorization: `Bearer ${token}` },31 cache: 'no-store'32 }).then(res => res.json());3334 return <div>Welcome, {user.name}</div>;35}
Architectural Explanation
The Rendering Strategy Spectrum
| Strategy | When HTML Is Created | Where It Is Served | TTFB | Server CPU Load | Freshness Guarantee |
|---|---|---|---|---|---|
| CSR | In browser via JS | CDN (empty shell) | Blazing fast shell, slow FCP | Zero origin compute | Real-time on client fetch |
| SSG | Build time | CDN edge cache | Fastest (<50ms) | Zero origin compute | Fixed at build time |
| ISR | Build time + background | CDN edge cache | Fast (<50ms) | Low background worker | Stale up to $N$ seconds |
| SSR | On every request | Origin server / Edge | Moderate (150–500ms) | High per user | Guaranteed real-time |
Core Architectural Mechanics:
- CSR (Client-Side Rendering): Traditional SPAs (Create React App, pure Vite). The server delivers an empty
<div id="root">and a large JavaScript bundle. The browser downloads, parses, and executes React before rendering content. This causes slow First Contentful Paint (FCP) and poor SEO for crawlers with strict rendering timeouts. - SSG (Static Site Generation): Next.js pre-renders HTML and JSON at build time. The static files are pushed to an Edge CDN. User requests hit the nearest edge node with near-zero latency.
- ISR (Incremental Static Regeneration): Combines the latency benefits of SSG with data freshness. A page is served from edge cache. If a request arrives after the revalidation interval has elapsed, Next.js serves the stale cached page immediately while triggering a background regeneration worker. Once the new page renders successfully, the edge cache is purged atomically.
- SSR (Server-Side Rendering): The server renders full HTML per incoming HTTP request. This is required whenever the output depends on request-time information, such as cookies, auth sessions, or geo-IP headers.
Common Mistakes & Anti-Patterns
Believing ISR guarantees that the visitor who triggers the revalidation receives the fresh page immediately (they receive the stale page; subsequent visitors receive the updated page).
Using SSR for public blog posts or marketing pages that do not depend on user-specific session cookies.
Assuming CSR provides better overall performance because the server serves a static file, ignoring high client-side CPU parse/execution times on low-end mobile devices.
Interview Follow-Up Traps
Interviewer asks: "What happens if an ISR background revalidation throws a database connection error?" Trap answer: The site crashes with a 500 error. Correct answer: Next.js catches the background build error and continues serving the previous valid cached version indefinitely until a subsequent regeneration succeeds.
Interviewer asks: "Can you run SSG on pages that check authentication cookies?" Trap answer: Yes, with edge rewrites. Correct answer: No. Any component or layout that reads cookies() or headers() opts the route out of static generation into dynamic request-time rendering.
Frequently Asked Questions
Does Next.js 15 cache fetch requests by default?
No. Next.js 15 changed fetch defaults to no-store (uncached). To enable caching, developers must explicitly specify next: { revalidate: N } or opt in via route segment configurations.
When should you choose SSR over SSG?
Choose SSR when the page content is highly personalized per user (e.g., private account dashboards) or requires immediate request-time query params or cookies.
How does client-side navigation work in Next.js between SSG pages?
Next.js prefetches the static React Server Component payload (RSC payload) and renders the page via client-side routing without triggering a full browser document reload.
Can ISR be triggered on demand rather than on a timer?
Yes. On-demand revalidation can be triggered programmatically via revalidatePath() or revalidateTag() in Route Handlers or Server Actions.
