Server-Side Rendering

Server-side rendering, or SSR, is the practice of generating a page’s HTML on the server when a request arrives and sending that finished HTML to the browser, so the user sees content immediately rather than waiting for JavaScript to build the page. It stands opposite to client-side rendering, where the server sends a near-empty HTML shell plus a JavaScript bundle that constructs the page in the browser.

The original web was entirely server-rendered. Systems like CGI scripts, PHP, and Ruby on Rails assembled an HTML document on every request and returned it. The rise of single-page applications in the early 2010s pushed rendering to the client for richer interactivity, but this created problems: a slow first paint, poor search-engine visibility, and heavy JavaScript downloads before anything appeared. SSR for JavaScript frameworks emerged to bring the benefits of server rendering back to component-based apps like React.

Modern frameworks describe a hybrid flow. In Next.js, layouts and pages are Server Components by default, which, as the documentation puts it, “lets you fetch data and render parts of your UI on the server, optionally cache the result, and stream it to the client.” Interactive pieces are marked as Client Components. On first load, the documentation explains, “HTML is used to immediately show a fast non-interactive preview of the route to the user,” and then “JavaScript is used to hydrate Client Components and make the application interactive.”

That two-stage sequence, server-rendered HTML first and client JavaScript second, is the defining shape of modern SSR. The server produces a meaningful HTML snapshot so the page is visible and crawlable right away, and the browser later attaches event handlers through a process called hydration to make it interactive.

SSR trades some server cost and complexity for better perceived performance, search optimization, and accessibility. Frameworks have continued to refine it with techniques like streaming the HTML in chunks, rendering only on demand, and combining it with static generation, so that today the line between “rendered on the server per request” and “pre-built ahead of time” is something developers choose per route rather than per application.