Today’s goal
Understand rendering as a placement and timing decision rather than a framework label.
We will connect:
- client-side rendering, server-side rendering, and static generation;
- hydration, serialization, handoff, and browser work;
- partial hydration, islands, streaming, and hybrid routes;
- revalidation, edge rendering, server components, and resumability;
- cacheability, personalization, authentication, and failure modes;
- performance as server, build, network, and device cost;
- a route-specific rendering decision matrix.
By the end of today you can
- explain where rendering happens and when it occurs;
- compare CSR, SSR, and SSG without slogans;
- identify hydration mismatch causes and handoff costs;
- isolate interactive regions with islands or client boundaries;
- design streaming boundaries that preserve UX and accessibility;
- distinguish server components from server-rendered HTML;
- reason about revalidation, edge execution, and resumability;
- select a rendering strategy per route;
- keep secrets and server-only data on the server;
- measure the rendering cost triangle instead of optimizing one metric.
SPA and CSR are related, not identical
CSR → where initial rendering happens
SPA → how navigation and application shell are organizedA site can use client rendering without being one large SPA.
An SPA can include server-rendered initial HTML.
Do not use the terms as interchangeable architecture decisions.
CSR and search engines
Search engines may execute JavaScript, but discoverability, timing, metadata, content quality, and operational behavior still matter.
Public content often benefits from HTML being available before client execution.
The correct choice depends on the content and delivery requirements.
SSR does not automatically improve every page
SSR can be a poor fit when:
- content is highly personalized and uncacheable;
- server data is slow;
- the page is mostly an internal interactive tool;
- hydration cost dominates;
- deployment cannot support reliable request rendering.
Measure the whole request-to-interaction path.
Hydration mismatches are signals
A mismatch can come from:
- random values;
- current time or timezone;
- browser-only APIs;
- different data on server and client;
- unstable IDs;
- conditional rendering based on client detection.
The warning often indicates an unclear rendering boundary or nondeterministic initial model.
Deterministic initial rendering
The server and client should agree on the initial representation.
Avoid using during initial render:
- random values;
- current time without a shared value;
- locale-dependent formatting without a fixed locale;
- browser state unavailable to the server.
Make the handoff data explicit.
Streaming and accessibility
As content arrives progressively:
- preserve logical document order;
- do not move focus unexpectedly;
- announce important updates appropriately;
- keep headings and landmarks coherent;
- avoid making keyboard users wait for a needed control without feedback.
Delivery timing must preserve usable structure.
Static generation and streaming can also mix
A statically generated shell can load or stream a dynamic region later through client or edge behavior.
The route may combine:
- prebuilt public content;
- request-time personalization;
- browser-side interactivity.
Hybrid is often a precise choice, not architectural inconsistency.
The server component payload has a cost
The browser may receive a structured description of server/client boundaries and data needed for the client tree.
Measure:
- payload size;
- serialization work;
- parsing;
- client boundary setup;
- repeated requests during navigation.
Moving logic server-side does not make all transfer cost disappear.
The “double data” oversimplification
SSR does not always mean the same data is fetched twice.
Possible designs include:
- server output only for static content;
- serialized data reused by the client;
- a client revalidation request by policy;
- server component payloads with selective transfer.
Inspect the actual network and handoff path.
Hydration versus resumability
| Hydration | Resumability |
|---|---|
| eagerly reconstructs client behavior | resumes behavior on demand |
| predictable component startup cost | more serialization and constraints |
| familiar event setup model | finer-grained lazy execution |
| browser executes more initially | browser may do less initial work |
Both require stable boundaries and explicit data transfer.
Authentication and rendering
Server rendering can check authentication before producing private output.
But ensure:
- private data is not cached publicly;
- redirects do not leak resource existence;
- serialized props do not contain excess data;
- client boundaries enforce appropriate behavior too.
Rendering location does not replace authorization policy.
Practical stages 1–4: establish the comparison
- Establish route data and interaction requirements.
- Build a CSR baseline.
- Create a minimal server-rendered version.
- Create a static version with explicit freshness assumptions.
Do not compare only screenshots. Compare the work and data path behind each result.
Practical stages 5–9: handoff and streaming
- Add streaming or a delayed independent region.
- Record the server-to-client handoff and hydration cost.
- Design streaming boundaries.
- Compare one large boundary with many tiny boundaries.
- Identify which regions truly need browser execution.
Measure timing and layout stability as well as total output.
Practical stages 15–19: reduce and justify browser work
- Delay island hydration.
- Explore resumability conceptually.
- Build a rendering decision matrix.
- Measure JavaScript responsibility.
- Draw the final hybrid architecture.
Verification: each topology has a stated freshness and interaction model, and server-only data stays server-side.
Common rendering smells
Watch for:
- entire site forced into CSR because one page is interactive;
- entire application SSR because “SSR is faster”;
- every component marked client-side;
- huge framework bundle for a static page;
- personalized region preventing the whole page from caching;
- slow widget blocking all server HTML;
- same data fetched on server and immediately fetched again on client.
Hydration mismatch is usually a modeling signal
Instead of suppressing the warning, ask:
- which value differs?
- who owns it?
- was it available on both sides?
- should it be client-only?
- should the server serialize a stable value?
- is the initial output deterministic?
Fix the rendering model before hiding the symptom.
SSG and content publishing
A publishing workflow should answer:
- when is a page rebuilt?
- how are previews generated?
- how is stale content invalidated?
- can a failed build leave the previous version live?
- which content requires request-time freshness?
Rendering strategy includes the authoring and deployment system.
Rendering topology and failure modes
build failure → previous deployment / publishing error
server data failure→ route or region fallback
client bundle fail → static content plus degraded interaction
hydration mismatch → deterministic handoff fix
stale output → revalidation or freshness messageDesign the failure path at the same time as the happy path.
Practical decision checklist
Ask:
- Is the content public?
- How often does it change?
- Is it user-specific?
- How interactive is it?
- Does it need browser-only APIs?
- Can the output be cached?
- Are data dependencies slow?
- Can interaction be isolated?
- How much state must cross to the browser?
- What happens after initial navigation?
Completion checklist
- route strategy is chosen from requirements rather than slogans;
- build, request, and browser work are identified;
- hydration output is deterministic;
- secrets and server-only data stay server-side;
- interactive boundaries are no larger than necessary;
- streaming boundaries have meaningful loading and error behavior;
- cacheability and personalization are separated where possible;
- freshness and revalidation are explicit;
- JavaScript and device cost are measured;
- deployment and failure behavior match the topology.
Misconceptions to leave behind (Part 1)
| Misconception | Better mental model |
|---|---|
| CSR means no server | It moves initial rendering work to the browser |
| SPA and CSR are identical | Navigation model and rendering location differ |
| SSR means no JavaScript | Interactive regions still need browser code |
| SSR is always faster | Server latency, hydration, and cacheability matter |
| SSG cannot be interactive | Static output can include client islands |
| Static means always fresh | Publication and revalidation define freshness |
Misconceptions to leave behind (Part 2)
| Misconception | Better mental model |
|---|---|
| Hydration rebuilds the DOM | It attaches client behavior to existing output |
| Streaming removes handoff cost | It changes delivery timing, not all work |
| Server components are just SSR | Execution location and HTML timing differ |
| Islands are automatically better | Coordination and boundary costs still exist |
| Edge is always faster | Runtime, data location, and cache behavior matter |
| Resumability is just faster hydration | It changes the server-client handoff model |