Next.js SSR renders React on the server per request, sending fully-formed HTML + hydration payload. Pros: fast LCP, SEO, social previews. App Router uses React Server Components + streaming SSR by default; Pages Router uses `getServerSideProps`. Tradeoff: server cost + TTFB depends on data fetches; cache where possible.
Category
Next.js
App Router, server components, SSR/SSG/ISR, hydration, and data fetching.
8 questions
In the Pages Router: getStaticProps runs at build (or on-demand revalidation) for SSG — fast, cacheable, perfect for content that doesn't change per-request. getServerSideProps runs on every request for SSR — needed when the response depends on cookies, headers, or per-user data. In the App Router (Next 13+), both are replaced by Server Components with fetch() options (cache, next.revalidate) — same SSG/SSR/ISR trade-offs, different API.
Next.js code-splits per route by default — each page becomes its own chunk plus a shared vendor chunk. Dynamic imports (`next/dynamic`) split inside pages. SSR happens per request: server renders the React tree, sends HTML + a `__NEXT_DATA__` payload, browser hydrates. App Router adds RSC (server-only components, ship less JS) and streaming SSR via Suspense.
Next/Image gives you on-the-fly resizing, modern formats (AVIF/WebP), responsive srcset, lazy loading, and reserved layout space (no CLS). Plain <img> needs you to wire all of that yourself.
Next.js loads `.env` files at build time per environment: `.env` (all), `.env.local` (all, gitignored), `.env.development` / `.env.production` (per NODE_ENV). `NEXT_PUBLIC_*` are inlined into the client bundle; everything else is server-only. `.env.local` overrides — for secrets and local config. Build-time inlining means changing public vars requires a rebuild.
Hydration: the client runs React on the same component tree the server already rendered, attaching event handlers and re-running effects, but **reusing existing HTML**. Mismatches happen when server and client render different output — caused by time/dates, browser-only APIs (`window`), random values, feature flags differing, or `useEffect`-style state read during render. Use `useId`, guard browser globals, serialize server data, or render client-only via dynamic imports.
A hydration error fires when the HTML the server rendered doesn't match what the client renders on first run. Causes: `new Date()`/`Math.random()`/`window.*` in render, locale/timezone mismatches, `typeof window` branches, third-party scripts mutating DOM before hydration, browser extensions modifying HTML. Fixes: client-only wrappers, suppressHydrationWarning for unavoidable cases, deterministic IDs (`useId`), check the actual DOM diff in the error message.
Hydration mismatches happen when server-rendered HTML doesn't match the client's first render. Common causes: time/locale, random IDs, browser-only APIs, third-party DOM mutations.