Tags: web-dev concept

Framework Rendering Modes

Date: 2026-08-19


Every meta-framework ships the same four strategies under four different names, and the marketing implies they’re competing products. They aren’t. The questions that actually differ between frameworks are what granularity you can choose at and what the default is when you don’t choose.


A rendering mode is a framework’s exposed control over when HTML is built and where. Which strategy to pick for a given page is Rendering Strategies; this note is about how frameworks let you express that choice, and what they hide.

The four, and what they’re called

StrategyWhen HTML is builtAlso sold as
StaticAt build time, onceStatic site generation (SSG), prerendering, static export
Server-renderedPer requestServer-side rendering (SSR), dynamic rendering, on-demand
Static + revalidationAt build, refreshed on a ruleIncremental static regeneration (ISR), on-demand revalidation
Client-renderedIn the browser, after loadSingle-page-app (SPA) mode, client-only routes

Streaming is not a fifth mode — it’s a property of the server-rendered ones: send the shell immediately, flush the rest as it resolves. See Streaming Responses.

The question that actually distinguishes frameworks

Granularity. Can a single route opt out of the app-wide default, and how is that expressed?

PER APP        one build target for everything
               simple, and wrong for any real site — a product page and a
               blog post have different freshness needs

PER ROUTE      an export, a config entry, or a file convention per route
               the useful granularity, and where most frameworks now sit

PER COMPONENT  islands and server components — one page, mixed modes

PER REQUEST    the same route static for anonymous visitors, dynamic once
               a session cookie exists

Per-component is Islands Architecture and Server Components. Per-route is the level most decisions live at. A storefront wants its product pages revalidating on a schedule, its basket never cached, its policy pages static and its account section dynamic — four modes in one application, chosen four times.

What the mode you picked implies

Three things travel with the choice, and forgetting them is where the trouble starts:

  • Caching. A statically generated page is cached by definition; a server-rendered one is cached only if you set headers saying so. “Server rendering is slow” is nearly always “server rendering with no cache headers” — HTTP Caching and CDN Caching
  • Where the code runs. Node, an edge worker, or a build container are three different runtimes with three different API surfaces. Code written against one breaks on another, usually at deploy time rather than in development
  • What’s knowable. A statically built page has no request: no cookies, no headers, no geolocation, no personalisation. Every attempt to personalise a static page ends up as a client-side patch after load, with the layout shift that implies — Cumulative Layout Shift

The default is the part to check

Frameworks differ far more in what happens when you don’t choose. Some make every route dynamic until proven otherwise; some prerender everything and force you to opt into a request. The consequence is a whole class of production surprise: a page that worked all through development becomes uncacheable because one component read a cookie, and nothing warned anyone.

The diagnostic question for any framework: what makes a route fall out of static rendering, and does it tell me when that happens? A build log that lists each route’s final mode is the feature that prevents this, and its absence is a real gap.

Where the leaks are

Mode is a build-time concept and freshness is a runtime one. Static-with-revalidation is the meeting point, and it’s the mode with the least standardised behaviour between frameworks — whether the stale page is served while revalidating, whether revalidation can be triggered by a webhook, whether it’s per-page or per-tag. See Static Generation and Revalidation, and verify against the specific tool rather than assuming.

[CHECK: mode names and per-route APIs are version-dependent and change between major releases. The four strategies are durable; the exported flag that selects them is not.]