AV
HomeAboutProjectBlog

© 2026 Ave syah Shina. All rights reserved.

  1. Home
  2. Blog
  3. 23 — SSR — When the Server Paints the First Frame

23 — SSR — When the Server Paints the First Frame

August 12, 202611 min read
Download as Markdown

"A Next.js feature" was how I filed server-side rendering, which conflated the technique with the frameworks that sell it. The separation: rendering is a spectrum of _when_ and _where_ the HTML is generated, not a single technique. SSR is one point on that spectrum — the point where the server builds the HTML on each request, before the browser sees the page.

"Server-side rendering" gets used two ways: narrowly, a specific mode (per-request, on the server); broadly, the whole family of "let the server produce HTML instead of leaving it to the browser." Only the spectrum view makes the trade-offs legible, so that's where I start.

The spectrum: when and where HTML is born

Every page has to become HTML at _some_ point — the question is when, and on which machine. Four answers, and most production sites mix them [1][2]:

  • CSR (Client-Side Rendering). The server ships a near-empty HTML shell plus a JS bundle. The browser downloads it, runs it, and the UI gets built in the browser. First paint is late and depends on JS executing.
  • SSR (Server-Side Rendering). The server runs the component tree on _every request_ and returns finished HTML. The browser paints real content immediately; JS then "hydrates" it — attaches the interactive behavior to the already-rendered HTML — to make it interactive [3].
  • SSG (Static Site Generation). HTML is rendered _once_, at build time. The server just hands out prebuilt files. Fast and cheap, but frozen until the next build.
  • ISR (Incremental Static Regeneration). Build-time HTML the server revalidates on a schedule or on demand. Static speed with the freshness of SSR.

Same page, four different moments the HTML exists:

build time user request first paint CSR empty shell + JS HTML built late late SSR server renders HTML ready early SSG built once · frozen served instantly earliest ISR built · then revalidated stale-while-revalidate early same page — four different moments the HTML becomes real

The shortcut I use now: CSR pushes the work onto the user's device and network; SSR (and its siblings) pull it back onto my server. The SEO, first-paint, and cost arguments are all consequences of that one shift.

Why SSR exists: content sooner, content crawlable

Two pressures pushed rendering back onto the server, and they're not the same problem.

First paint. Under pure CSR the browser receives an empty <div id="root"></div> and a script tag. The user stares at a blank screen until the JS downloads, parses, executes, fetches data, and writes to the DOM. On a slow phone that's a long, visibly empty wait. SSR shortens it: the HTML that comes back already _is_ the page, so the browser paints content on the first frame and hydrates it into an app afterward [3]. Interactivity still needs JS; the _content_ doesn't wait for it.

Crawlability. A search crawler historically had limited patience for running JavaScript [4]. Send it an empty shell and it may index exactly that — nothing. Send it rendered HTML and it reads headings, links, and text like a browser. That's why SSR is non-negotiable for content sites that depend on search traffic: the page has to _be_ something before any script runs.

So SSR trades one kind of cost for another. I give up the simplicity of a static bundle and the cheapness of a CDN-only deploy, and in return I take on a running server that has to render on every request. For a marketing site or a docs site, that trade is often a bad one and SSG wins. For a dashboard, an e-commerce catalog, or anything per-user and time-sensitive, SSR is what makes the page actually useful.

The trade-off, said plainly

SSR is not free, and the version I had in my head — "just turn it on, it's better" — was what needed correcting.

  • Server load. Every request executes my component tree, often with data fetches. Real CPU on a real box, scaled with traffic. A viral spike under CSR mostly hits my CDN; under SSR it hits my render servers.
  • Latency to first byte. The browser can't paint until the server finishes rendering. A slow database query _is_ a slow first byte now — under CSR that query happened after paint, in the browser.
  • Complexity. Hydration has rules: server and client must agree on the output, or React warns about mismatches; window/document don't exist on the server; data fetching must resolve before render. A whole class of bugs CSR simply doesn't have.
  • Caching is the whole game. Because every request _can_ render, the question is which _should_. SSG and ISR are SSR's answers to "render once" and "render sometimes" — choosing between them per-route is most of the real work.

SSR buys better first paint and real crawlability, and charges you server cost, TTFB (time to first byte) sensitivity, and a stricter way of thinking. Pick it where content is dynamic or SEO-critical; pick SSG/ISR where it isn't.

The frameworks that make it ergonomic

The technique predates all of them — PHP and Rails rendered HTML on the server before "SPA" (single-page application) was a word. What changed is that React, Vue, and Angular were born as _client_ renderers, and bringing them back to the server required real plumbing: a renderer that runs components in Node, a router that works on both ends, a data-fetching layer that resolves before render, and a hydration step on the client. That plumbing is what the meta-frameworks (frameworks built on top of a component library) package up.

Component renderer that runs on the server React · Vue · Angular — originally client-only Meta-framework plumbing routing · pre-render data fetching · hydration · caching Next.js React · React Server Components Nuxt Vue · hybrid rendering Angular Universal TanStack Start (React)

Next.js (React). The one that pushed SSR-by-default into the mainstream for React, and the one this site is built on. Each route picks its rendering mode — SSR for a dashboard, SSG for a blog post, ISR for a list that revalidates on a tag. The App Router pushed the model further with React Server Components, where components run on the server by default and ship only the JS they need [5]. Next made "where does this render?" a per-route question.

Nuxt (Vue). Vue's answer to the same problem, and the symmetry with Next is deliberate — file-based routing, a Nitro server engine for Node or the edge (servers close to the user), and "hybrid rendering": a per-route config mixing SSR, SSG, ISR, and SPA in one app [6].

Angular (Universal). Took server rendering seriously earliest of the three, via Angular Universal — server-side rendering plus build-time prerendering [7]. Same spectrum; the framework's opinionated structure (DI — dependency injection, its way of handing components what they need — modules, templates) just makes the plumbing feel different.

TanStack Start (React). A newer React full-stack framework on TanStack Router, with SSR as a first-class default rather than a bolt-on [8]. The same bet the others are making — routing, server functions, data fetching, and rendering mode in one coherent layer — expressed with TanStack's primitives.

The pattern across all of them: the underlying component library (React, Vue, Angular) is the renderer; the meta-framework decides _when_ to call it and _where_, plus the plumbing — routing, data, hydration, caching. Once I saw it that way, "which framework should I learn" stopped being a question about SSR and became a question about my component library.

How I use this

The habit these notes left me with is a per-route question instead of a per-app one: _how dynamic is this content, and who needs to read it?_ Static and public (a blog post) → SSG. Static-ish with occasional updates (a project list) → ISR. Per-user or time-sensitive (a dashboard, a cart) → SSR. Interactive-only behind auth where SEO is irrelevant → CSR is honestly fine. SSR isn't the upgrade path I thought it was; it's one option on a slider.

References

[1] Mozilla, "Client-side rendering (CSR)," MDN Web Docs, 2024. [Online]. Available: https://developer.mozilla.org/en-US/docs/Glossary/CSR

[2] Vercel, "Rendering: The four rendering models," Next.js Learn, 2024. [Online]. Available: https://nextjs.org/learn/dashboard-app/rendering

[3] Mozilla, "Server-side rendering (SSR)," MDN Web Docs, 2024. [Online]. Available: https://developer.mozilla.org/en-US/docs/Glossary/SSR

[4] Google, "Understand how search works with JavaScript," Google Search Central documentation, 2024. [Online]. Available: https://developers.google.com/search/docs/crawling-indexing/javascript/javascript-seo-basics

[5] Vercel, "Rendering fundamentals," Next.js Documentation, 2024. [Online]. Available: https://nextjs.org/docs/app/building-your-application/rendering

[6] NuxtLabs, "Rendering modes," Nuxt Documentation, 2024. [Online]. Available: https://nuxt.com/docs/guide/concepts/rendering

[7] Angular Team, "Server-side rendering (SSR) with Angular," Angular Documentation, 2024. [Online]. Available: https://angular.dev/guide/ssr

[8] TanStack, "TanStack Start overview," TanStack Documentation, 2025. [Online]. Available: https://tanstack.com/start/latest/docs/framework/react/overview

Knowledge check · Question 1 of 5

Under pure CSR, what does the browser receive on the first request?

Comments

Leave a Comment

You must be signed in to comment

0 Comments

No comments yet. Be the first to comment!