Rendering Strategies Overview
The Rendering Strategy Spectrum
Choosing how and where to render your UI is the single most impactful architectural decision for web performance. The strategy determines how quickly users see content, how much JavaScript ships to the browser, and how responsive the page feels once loaded. In 2026, the landscape has expanded well beyond the simple CSR-vs-SSR binary into a rich spectrum of approaches — each with distinct trade-offs across initial load speed, interactivity, SEO, server cost, and development complexity. Most modern applications benefit from mixing strategies on a per-route or even per-component basis rather than committing to a single approach.
Client-Side Rendering (CSR)
In CSR, the server delivers a minimal HTML shell and a JavaScript bundle. The browser downloads, parses, and executes the JavaScript, which then fetches data and renders the UI entirely on the client. This was the default model for React SPAs for years and remains appropriate for highly interactive applications behind authentication (dashboards, admin panels, internal tools) where SEO is irrelevant and the user has already committed to waiting for the app to load.
The performance cost is well-understood: the user sees a blank page (or loading spinner) until JavaScript finishes executing, producing poor LCP and FCP. On slow devices and networks, this delay can be several seconds. CSR also creates a “waterfall” problem — the HTML loads, then JavaScript loads, then data fetches begin, creating sequential dependencies. In 2026, CSR-only is almost exclusively reserved for post-authentication interactive features, not for fetching external data or rendering initial page content.
Resources:
Server-Side Rendering (SSR)
SSR generates full HTML on the server for each request. The browser receives meaningful, rendered content immediately — great for LCP and SEO — and then JavaScript “hydrates” the page to make it interactive. This is the foundation of modern meta-frameworks: Next.js, React Router v7 (formerly Remix), SvelteKit, and Nuxt.
The trade-off is server cost and Time to First Byte (TTFB). Every request requires server-side computation, which can be slow if it involves database queries, API calls, or heavy rendering logic. The hydration step also means the page appears loaded but isn’t truly interactive until JavaScript finishes executing — a gap that frustrates users (the “uncanny valley” of SSR). Modern frameworks address this with streaming SSR and progressive/selective hydration (covered in Sections 9–10).
Resources:
Static Site Generation (SSG) & Incremental Static Regeneration (ISR)
SSG pre-renders all pages to static HTML at build time, producing files that can be deployed to any CDN for near-instant delivery. It provides the best possible TTFB and LCP for content that doesn’t change frequently — blogs, documentation, marketing pages, landing pages. The limitation is obvious: any content change requires a rebuild and redeploy, and build times scale linearly with page count.
Incremental Static Regeneration (ISR), pioneered by Next.js, bridges this gap. Pages are pre-built at deploy time but can be revalidated in the background at runtime on a configurable schedule or on-demand. When a user requests a stale page, they receive the cached version instantly while the server regenerates a fresh version for subsequent visitors. This combines SSG’s speed with SSR’s freshness, making it ideal for large e-commerce catalogs, news portals, and any site with frequently changing but cacheable content. The trade-off: users may briefly see stale content during the revalidation window.
Resources:
- Static Generation — Next.js Docs
- Incremental Static Regeneration — Next.js Docs
- Astro Static Mode — Astro Docs
Streaming SSR
Traditional SSR waits for the entire page to render on the server before sending any HTML to the browser. Streaming SSR sends HTML in chunks as it’s generated, allowing the browser to start parsing and rendering content progressively. React 18’s streaming SSR with <Suspense> boundaries makes this practical: fast-loading parts of the page (header, navigation, above-the-fold content) stream immediately, while slower parts (data-dependent sections, below-the-fold content) show fallback loading states and stream in when ready.
This dramatically improves perceived performance — users see meaningful content within milliseconds even if parts of the page are still loading. It also improves TTFB because the first byte is sent as soon as the shell is ready, not after the slowest data fetch completes. Next.js App Router, React Router v7, and SvelteKit all support streaming out of the box. The combination of streaming SSR with Suspense boundaries is the recommended default approach for dynamic React applications in 2026.
Resources:
- Streaming SSR in React 18 — React Docs
- Streaming — Next.js Docs
- Suspense for Data Fetching — React Docs
Islands Architecture
The Islands architecture, coined by Katie Sylor-Miller and popularized by Preact creator Jason Miller, renders the page as mostly static HTML with isolated “islands” of interactivity that hydrate independently. Unlike SPAs where the entire page hydrates as one large JavaScript application, Islands architecture hydrates only the specific components that require client-side JavaScript — a header search bar, an image carousel, a comments widget — while the rest remains zero-JS static HTML.
Astro is the most prominent implementation. It ships zero JavaScript by default; you explicitly opt components into client-side hydration using directives like client:load (hydrate immediately), client:idle (hydrate during idle time), client:visible (hydrate when scrolling into viewport), or client:media (hydrate when a media query matches). Islands hydrate in parallel and independently — a heavy carousel below the fold doesn’t block the header from becoming interactive. Crucially, Astro is framework-agnostic: you can use React, Vue, Svelte, SolidJS, or Preact components together in the same project, each hydrated as its own island.
This architecture excels for content-heavy sites (blogs, documentation, marketing pages, e-commerce storefronts) where 80%+ of the page is static content and only a few discrete regions need interactivity. It consistently produces the best Lighthouse scores — Astro achieved a 99.2 average score in the Enterspeed benchmark study. The trade-off: it requires thinking about component boundaries differently, and highly interactive, SPA-like applications with deeply interconnected state don’t map well to isolated islands.
Resources:
Resumability (Qwik)
Qwik, created by Miško Hevery (the original creator of Angular), introduces a fundamentally different paradigm: resumability. Instead of hydrating the entire app on the client — which means re-executing JavaScript to reconstruct the component tree, re-attaching event listeners, and rebuilding application state — Qwik serializes the application’s execution state on the server and sends it as HTML attributes. The client simply resumes from where the server left off, with zero hydration cost.
Every component, event handler, and closure in Qwik is automatically code-split into its own lazy-loadable chunk. JavaScript is only downloaded when a user actually interacts with a specific element — click a button, and only that button’s handler is fetched and executed. This means Qwik apps are interactive almost instantly regardless of application size, because the amount of JavaScript executed at startup is effectively zero. The approach delivers exceptional Core Web Vitals, particularly INP and TBT.
The trade-off is developer experience and ecosystem maturity. Qwik requires thinking in terms of resumable closures ($ suffix functions), which is a mental model shift from traditional React or Vue. The ecosystem is significantly smaller than React’s. However, Qwik can now be used as a UI framework inside Astro — combining Astro’s island architecture with Qwik’s resumability, so islands that would normally require hydration directives (client:load) work automatically without any hydration step.
Resources:
Partial Prerendering (PPR)
Partial Prerendering is an experimental Next.js feature that combines static and dynamic rendering within a single page request. The static shell of the page (navigation, layout, any content that doesn’t depend on request-specific data) is served instantly from the edge cache, while dynamic “holes” (personalized content, real-time data) stream in via Suspense boundaries. This means you get the TTFB benefits of static generation and the freshness of SSR in one request, without configuring separate rendering strategies per route.
PPR represents the direction modern frameworks are heading: rather than choosing one rendering strategy per page, the framework automatically determines which parts of each page can be static and which need to be dynamic. Vercel’s vision is that PPR will eventually simplify the mental model — you write your components, mark the dynamic parts with Suspense, and the framework handles the rest.
Resources:
Decision Framework: Which Strategy When?
Rather than choosing a single strategy, think in terms of what each page (or component) needs:
Content doesn’t change? → SSG. Deploy to CDN, serve instantly. Best possible performance.
Content changes periodically? → ISR. Pre-build at deploy, revalidate on schedule or on-demand. Near-static speed with freshness.
Content changes per-request or is personalized? → SSR with streaming. Send the static shell immediately, stream dynamic content as it’s ready.
Page is mostly static with a few interactive widgets? → Islands (Astro). Zero JS for static parts, selective hydration for interactive parts.
Highly interactive application (dashboard, editor, tool)? → SSR + selective hydration (React Server Components), or CSR for fully client-side features. Consider Qwik’s resumability for instant interactivity at any scale.
Mix of static and dynamic on the same page? → PPR (Next.js experimental) or streaming SSR with Suspense boundaries.
The meta-frameworks (Next.js, Astro, React Router v7, SvelteKit) all support mixing these strategies within a single application. The best architecture uses the lightest rendering strategy that meets each page’s requirements.
Resources: