Rendering Topology Comparison: CSR, SSR, and Static Delivery
Practical 11 - Rendering Topology Comparison: CSR, SSR, and Static Delivery
Related: Chapter 11 · Lecture slides
Objective
Evaluate and measure the concrete performance, architectural, and data-flow trade-offs between Client-Side Rendering (CSR), Server-Side Rendering (SSR), and Static Site Generation (SSG) across identical route requirements: the Municipal Public Permit Catalogue.
By completing this laboratory, you will:
- Instrument the Performance Triangle: Measure runnable metrics - Time to First Byte (TTFB), First Contentful Paint (FCP), total transferred JavaScript bytes, and Time to Interactive (TTI) - across different topologies.
- Audit the State Handoff Boundary: Inspect the serialized data payload transferred from server to client to prevent secret leakage and double-fetch overhead.
- Analyze Hydration Costs: Observe the “uncanny valley” where server-rendered HTML is visible on screen but unclickable until client hydration finishes walking the DOM.
- Distinguish Runnable Measurements from Conceptual Topologies: Conduct hands-on measurements for the core three topologies (CSR, SSR, SSG), while evaluating advanced topologies (Streaming and Islands) through structured architectural analysis.
Workspace Setup
Set up a minimal Node.js / TypeScript environment with local instrumentation tools:
Ensure your tsconfig.json targets ES2022 with "moduleResolution": "node".
The Shared Catalogue Specification
All three implementations must render the exact same public data model and layout:
Stage-by-Stage Implementation
Stage 1: The Client-Side Rendered (CSR) Baseline
In CSR, the web server acts merely as a dumb static file host. The server returns a near-empty HTML shell:
In src/csr-bundle.ts, implement the client orchestrator:
- When mounted, fire
fetch('/api/permits'). - Await the JSON response.
- Dynamically construct HTML strings or DOM elements and insert them into
#root. - Measure the latency gap between DOMContentLoaded and First Contentful Paint.
Stage 2: Pre-rendered Static Delivery (SSG / Edge HTML)
In SSG, the HTML is pre-computed at build time. There is zero server execution latency at request time:
Verification Requirement:
Serve dist/ssg/index.html using a simple HTTP server (npx serve dist/ssg). Verify that:
- TTFB is under 25ms.
- The document content is visible immediately without requiring client JavaScript execution.
Stage 3: Server-Side Rendering (SSR) & State Handoff
In SSR, the server receives the incoming HTTP request, queries the database at request time, and generates dynamic HTML tailored to query parameters (e.g. ?category=Hospitality):
Stage 4: The Hydration Script and Handoff Audit
In src/ssr-client-hydrate.ts, implement the client hydration phase:
Security Audit Check:
Inspect the generated HTML source. Verify that:
- No internal connection strings, database passwords, or unscrubbed administrative notes exist in
<script id="__PERMIT_DATA__">. - All serialized JSON text escapes
<as\u003cto eliminate Cross-Site Scripting (XSS) script breakout vulnerabilities.
Architectural Comparison Matrix
Record your measurements and architectural observations in the following comparison table:
| Dimension | Client-Side Rendering (CSR) | Server-Side Rendering (SSR) | Static Site Generation (SSG) |
|---|---|---|---|
| Initial HTML Size | ~1.5 KB (skeleton only) | 12–40 KB (full markup + JSON) | 10–30 KB (full markup, 0 JSON) |
| Time to First Byte (TTFB) | ~20 ms (static edge host) | 80–300 ms (server DB query latency) | <20 ms (global CDN cache) |
| First Contentful Paint (FCP) | Slow (blocked by JS download & API) | Fast (instant paint of HTML) | Fastest (instant paint of static HTML) |
| Time to Interactive (TTI) | Synchronized with FCP | Lagging FCP (the “uncanny valley”) | Immediate (or zero if no JS needed) |
| SEO Indexability | Reliant on search bot JS execution | Universal (raw HTML available) | Universal (raw HTML available) |
| Server Compute Overhead | Zero (static assets only) | High (CPU & memory per request) | Zero at runtime (build-time only) |
| Content Freshness | Always fresh (client queries API) | Real-time per request | Stale until next build/revalidation |
Optional Conceptual Extensions
- Streaming SSR with Suspense: Analyze how flushing HTTP headers and the outer App Shell immediately while streaming slow table rows in subsequent chunks eliminates the TTFB penalty of traditional SSR.
- Island Architecture (Astro / Fresh): Evaluate how isolating client hydration strictly to the
.btn-inspectbuttons (leaving 95% of the page as unhydrated static HTML) eliminates the client JavaScript bundle overhead.
Deliverables & Submission Checklist
-
src/types.ts: Domain models for the permit catalogue. -
dist/csr/index.html&src/csr-bundle.ts: Fully working client-rendered baseline. -
src/ssg-builder.ts: Static HTML compilation script. -
src/ssr-server.ts: Node.js HTTP server rendering dynamic HTML with safe serialized state handoff. -
src/ssr-client-hydrate.ts: Non-destructive DOM hydration script. - Completed Architectural Comparison Matrix with local measurements.