Modern frontend frameworks give developers several strategies for delivering content to the browser. Choosing the right one dramatically affects performance, SEO, and user experience. This post covers the four most important rendering methods — CSR, SSR, SSG, and Hydration — with a diagram for each.
Client-Side Rendering (CSR)
In CSR the browser downloads a minimal HTML shell and a JavaScript bundle. The JS then runs in the browser, fetches data, and constructs the full page on the client.
Frameworks: React (CRA / Vite SPA), Vue (Vite SPA), Angular
How CSR works step by step
- Browser requests the page → server returns a nearly empty HTML file
- Browser downloads the JavaScript bundle
- JS runs in the browser and builds the DOM
- Data is fetched from APIs and the UI is rendered
⚠️ The page is completely blank until the JS bundle has downloaded and executed. This hurts both perceived performance and SEO crawlers that don't run JS.
Pros and Cons
| ✅ Pros | ❌ Cons |
|---|---|
| Rich, app-like interactions | Slow initial load (blank screen) |
| Low server load | Poor SEO out of the box |
| Simple deployment (static host) | Large JS bundles |
| Fast navigation after first load | Requires JS enabled |
Best for: Dashboards, admin panels, apps behind a login, real-time tools.
Server-Side Rendering (SSR)
With SSR the server generates the full HTML for each request. The browser receives a complete, readable page immediately. JavaScript then runs to make the page interactive.
Frameworks: Next.js (getServerSideProps), Nuxt.js, SvelteKit, Remix
How SSR works step by step
- Browser sends a request for a page
- Server fetches data from the database or API
- Server renders the full HTML and sends it to the browser
- Browser displays the HTML immediately (fast First Contentful Paint)
- Browser downloads JS and hydrates the page to add interactivity
⚠️ This entire cycle runs on every request. The server must be available, fast, and horizontally scalable.
Pros and Cons
| ✅ Pros | ❌ Cons |
|---|---|
| Excellent SEO | Higher server load per request |
| Fast initial paint (content visible) | More complex infrastructure |
| Dynamic, always-fresh data | Cold start delays (serverless) |
| Works without JS | Slower than static file serving |
Best for: E-commerce product pages, news articles, pages that need fresh data on every request.
Static Site Generation (SSG)
SSG pre-renders all pages at build time. The result is a set of plain HTML files deployed to a CDN. No server is needed at request time.
Frameworks: Next.js (getStaticProps), Gatsby, Astro, Hugo, Eleventy
How SSG works step by step
- At build time, the framework fetches all data and renders every page to HTML
- The HTML files are uploaded to a CDN
- At request time, the browser gets the pre-built HTML from the nearest CDN edge node — no server execution needed
⚠️ Data can become stale between builds. A new deploy is required for content changes unless ISR (Incremental Static Regeneration) is used.
Pros and Cons
| ✅ Pros | ❌ Cons |
|---|---|
| Blazing fast (files from CDN edge) | Data can become stale |
| Excellent SEO | Rebuild required for content changes |
| Highly scalable (no server) | Long build times for large sites |
| Very secure | Not suitable for user-specific pages |
Best for: Blogs, documentation sites, marketing pages, portfolios.
Hydration
Hydration is the process that makes a server-rendered or statically generated HTML page interactive. The browser receives full HTML (fast paint), then JS is loaded and "wired up" to the existing DOM — attaching event listeners and state without re-rendering.
The Hydration problem
Hydration introduces Time To Interactive (TTI): the page looks ready but is not clickable until JS finishes hydrating. On slow networks or heavy JS bundles, this gap frustrates users.
FCP ─────────────────────────────────► TTI
(page visible) (page usable)
│◄─── JS downloads + hydrates ──►│
Modern solutions
- Partial Hydration — only hydrate interactive components (Astro Islands)
- Progressive Hydration — hydrate as components enter the viewport
- Resumability — skip hydration entirely by serializing state (Qwik)
All Methods Compared
| CSR | SSR | SSG | Hybrid (SSR+SSG) | |
|---|---|---|---|---|
| First Load Speed | 🔴 Slow | 🟡 Medium | 🟢 Fast | 🟢 Fast |
| SEO | 🔴 Poor | 🟢 Excellent | 🟢 Excellent | 🟢 Excellent |
| Data Freshness | 🟢 Real-time | 🟢 Per-request | 🔴 Build-time | 🟡 Configurable |
| Server Cost | 🟢 Low | 🔴 High | 🟢 None | 🟡 Medium |
| Scalability | 🟡 Medium | 🔴 Harder | 🟢 Excellent | 🟢 Good |
| Interactivity | 🟢 Rich | 🟡 After hydration | 🟡 After hydration | 🟡 After hydration |
| Complexity | 🟢 Simple | 🟡 Medium | 🟢 Simple | 🔴 Complex |
When to use each method
Use CSR when:
- Building authenticated apps (dashboards, admin panels)
- Data changes frequently and SEO doesn't matter
- You need rich, complex client-side interactions
Use SSR when:
- Pages need fresh data on every request
- SEO is critical and content changes frequently
- You're building e-commerce or social platforms
Use SSG when:
- Content doesn't change often (blogs, docs, portfolios)
- You want maximum speed and zero server cost
- Pages are the same for every user
Use Hybrid (SSG + SSR + ISR) when:
- Some pages are static, some are dynamic
- You need incremental rebuilds (ISR) to keep static pages fresh
- You want per-page control over the rendering strategy
The modern consensus: Most production apps benefit from a hybrid approach. Frameworks like Next.js, Nuxt.js, and SvelteKit let you choose the rendering strategy per page, so you can statically generate your marketing pages while server-rendering your product listings and client-rendering your dashboard.