Blog PostServer Components aren't SSR!
Published on June 2025 by Anthony
React Server Components vs. Server-Side Rendering: what’s really happening under the hood
React now offers two server-focused techniques that solve different performance problems. Mixing them up leads to confusion and wasted optimisation effort. Here’s a concise, corrected primer.
1Server-side rendering (SSR)
Classic SSR—used by the old Pages Router in Next.js—executes a React tree on the server, converts the JSX to plain HTML, and sends that markup to the browser. Hydration then attaches React’s runtime so the page becomes interactive. Because actual HTML is transmitted, you can open View Source and see the skeleton (titles, table frames, meta tags, etc.) even if client-side data later refines parts of the UI.
2Why SSR can block
The server must finish every expensive task before it starts streaming. A page that fetches a big data table and renders a complex chart stalls until both are done, stretching Total Blocking Time (TBT) and delaying First Contentful Paint.
3React Server Components (RSC)
RSC solves a different bottleneck: over-shipping JavaScript. A server component never reaches the browser as JS or HTML. Instead, the server renders it into a compact, JSON-like stream describing the component tree and its data. The client receives that stream, reconstructs the subtree, and merges it with interactive client components. Each subtree’s fetch can resolve independently, so fast bits appear immediately while slow ones continue streaming.
4Streaming SSR + RSC in the App Router
Next.js 13+ pipes these ideas together. The HTML shell for client components starts streaming as soon as it’s ready, while RSC payloads arrive asynchronously and hydrate only where needed. This:
slices TBT by avoiding all-or-nothing renders
lets you cache server-only fragments aggressively
removes unused browser JavaScript altogether
Key take-aways
SSR outputs HTML; RSC outputs a serialised component payload.
Streaming mitigates blocking; RSC eliminates it for non-interactive chunks.
Keep data-heavy, read-only UI in server components; reserve client components for anything that touches the DOM, browser APIs, or user input.
Used together, they deliver faster first paint and smaller bundles without sacrificing rich interactivity.