Build time, request time, or browser runtime?
Lesson 01 · Advanced frontend rendering
Rendering is a coordinate system
Estimated time: about 12 minutes
The senior-level move is not naming more acronyms. It is separating independent decisions, then composing them from product constraints.
Four axes, not one ladder
A page can be static and streamed, server-rendered and partially hydrated, or built from Server Components while still producing cached HTML. Start with these four questions.
Per user, cached globally, or revalidated after a freshness window?
One complete response or streamed boundaries?
No JavaScript, full hydration, islands, selective hydration, or resume?
The options, by the problem they solve
CSR / SPA
browser produces UIThe server sends a small shell; JavaScript fetches data and constructs the meaningful DOM. Rich post-load transitions are natural, but initial content competes with download, parse, execution, and data round trips.
Best fit: authenticated, interaction-heavy tools where discovery and first-load content are secondary.
SSR
request produces HTMLA server creates HTML for each request. It can use cookies and fresh data, improving initial content delivery, but adds compute and can worsen TTFB. SSR does not automatically mean “less JavaScript.”
Best fit: personalized or highly fresh pages whose initial content matters.
SSG / prerendering
build produces HTMLHTML is created ahead of traffic and served from a CDN. This minimizes request work and failure surface, but freshness is tied to builds or invalidation and large page sets can make builds expensive.
Best fit: documentation, editorial content, landing pages, stable catalog data.
ISR / revalidation
cache refreshes laterA cached static result is served while the system periodically or explicitly regenerates it. This trades bounded staleness and cache coordination for CDN-like reads without full rebuilds.
Best fit: large content sets that change, but do not require per-request freshness.
Streaming SSR
HTML arrives in chunksThe server flushes a useful shell, then resolves slower regions across boundaries. Streaming changes response timing—not where the page is fundamentally rendered—and demands stable fallbacks, error isolation, and infrastructure that does not buffer.
Best fit: request-rendered pages with uneven data latency and independently useful regions.
Islands / partial hydration
only regions activateMost of the document stays inert HTML; isolated widgets receive JavaScript and hydrate independently. It sharply limits client work but makes cross-island state and application-wide interaction more deliberate.
Best fit: content-first sites with a handful of interactive widgets.
Server Components
code stays server-sideComponents that need no browser capability execute only on the server and send a serialized UI description, while Client Components define interactive boundaries. This is a component execution and payload model—not a synonym for SSR.
Best fit: component trees where data access and non-interactive dependencies should never enter the client bundle.
Resumability
state resumes on demandInstead of eagerly replaying the component tree to hydrate, the server serializes enough state and listener references for client execution to continue lazily. Startup work drops; serializability constraints and ecosystem choices rise.
Best fit: experiences where startup JavaScript is the dominant constraint and the framework model is acceptable.
Four distinctions interviewers probe
SSR ≠ hydration
SSR produces HTML. Hydration attaches a client runtime to existing HTML. A server-rendered page can remain progressively enhanced with little or no hydration.
Streaming ≠ Server Components
Streaming is transport over time. Server Components decide where component code executes and what crosses the boundary. They often cooperate, but solve different problems.
Edge ≠ rendering model
“Edge rendering” relocates request-time work nearer users. The work may still be SSR, personalization, or cache assembly, with new runtime and data-distance constraints.
Fast HTML ≠ fast interaction
FCP can improve while INP suffers if a large hydration task follows. Discuss HTML arrival, JavaScript cost, main-thread work, and interaction readiness separately.
Retrieval drill: make the boundary
Scenario: A public product page has stable copy and images, inventory changes every few seconds, the cart is user-specific, and only the gallery and “add to cart” controls are interactive. What is the strongest starting architecture?
Choose first. Then explain the production, reuse, delivery, and activation decisions aloud before reading the feedback.
A senior-shaped interview answer
“I would not choose one rendering label for the whole page. I’d first separate freshness, personalization, and interactivity boundaries.”
“The product shell is cacheable, so I’d prerender it and revalidate on catalog updates. Inventory and cart are request-aware; I’d stream or fetch those behind stable placeholders, depending on whether they must be present in the initial response. Only the gallery and cart controls need client JavaScript.”
“I’d validate the choice with cache-hit rate, TTFB, LCP, shipped JavaScript, INP, stale-data tolerance, and failure behavior. If inventory correctness is transactional, the add-to-cart action must re-check it regardless of what the page rendered.”
Primary reading
- Rendering on the Web — the best first-pass taxonomy and performance model.
- React: renderToPipeableStream — see exactly what shell-first streaming means.
- Astro: Islands architecture — contrast whole-app and component-level activation.
- Next.js: Server and Client Components — study the execution boundary separately from SSR.