Modern App Dev - Rendering and Build Processes

Created on February 16, 2025

1. Rendering Strategies

Rendering determines where, when, and how the final HTML and visible content are created.

1.1 Client-Side Rendering (CSR)

A minimal HTML file containing a JavaScript bundle is sent to the browser.
The browser downloads and executes the JavaScript.
The JavaScript then fetches data (typically through API calls) and builds the complete page in the browser.

Characteristics

  • Fast delivery of initial empty shell
  • Slow appearance of real content
  • Excellent interactivity once loaded
  • High client CPU and memory usage
  • Poor to moderate SEO
  • Low server load after assets are served

Typical use cases
Highly interactive applications, dashboards, internal tools, single-page applications where initial load speed is less critical than responsiveness.

1.2 Server-Side Rendering (SSR)

For each incoming request, the server fetches data, runs business logic, and generates complete HTML.
The fully rendered HTML is sent to the browser.
The browser then hydrates the page (attaches JavaScript event handlers and state).

Characteristics

  • Fast first contentful paint with complete content
  • Always fresh, per-request data
  • Excellent SEO
  • Higher server CPU usage that scales with traffic
  • Hydration still required for interactivity
  • Potential delay in time-to-interactive

Typical use cases
E-commerce product pages, news articles, personalized content, any page where SEO and fast perceived load matter.

1.3 Static Site Generation (SSG)

During the build process (before deployment), all routes and required data are known.
Every page is pre-rendered into plain HTML, CSS, and JavaScript files.
These static files are deployed to a CDN or static host.

Characteristics

  • Near-instant delivery from edge cache
  • Zero runtime server computation
  • Excellent performance and SEO
  • Maximum security (no server runtime)
  • Content is fixed at build time
  • Any update requires a full rebuild and redeploy

Typical use cases
Documentation sites, blogs, marketing pages, portfolios, landing pages, content that changes infrequently.

1.4 Incremental Static Regeneration (ISR)

Pages are generated statically at build time (like SSG).
A revalidation interval is defined (time-based or event-triggered).
When a request arrives after the interval, the stale page is served immediately while a background process generates a fresh version.
Future requests receive the updated page.

Characteristics

  • Performance and cost similar to SSG
  • Data freshness improved over pure SSG
  • Brief periods of staleness possible
  • Very low runtime compute cost

Typical use cases
News portals, product catalogs, blogs with occasional updates, large sites needing a balance between speed and freshness.

1.5 Partial Prerendering (PPR)

An advanced hybrid strategy (popularized in Next.js 14+ and stabilized in later versions) that prerenders a static “shell” of the page at build time (layouts, static components, navigation, etc.), while leaving dynamic “holes” for personalized or request-time content.

These dynamic parts are filled via streaming (often using React Suspense boundaries) at request time.

Characteristics

  • Extremely fast static shell delivery (edge-cached like SSG)
  • Dynamic sections load asynchronously without blocking the shell
  • Excellent performance, SEO, and perceived load time
  • Static by default, dynamic only where needed (cookies, headers, uncached fetches)
  • Requires Suspense-aware components and framework support (Next.js App Router)
  • Combines best aspects of SSG + SSR in a single route

Typical use cases
Dashboards with static layout + personalized widgets, e-commerce pages with fixed product info + user-specific carts/recommendations, content sites with static articles + dynamic comments/view counts.

1.5.1 ISR vs Partial Prerendering (PPR) – Key Differences

Aspect Incremental Static Regeneration (ISR) Partial Prerendering (PPR)
Granularity Operates at the page/route level – regenerates entire page Operates at the component/section level within a single route
Static Portion Full page is static until revalidation Static shell (layouts, nav, non-dynamic parts) prerendered at build
Dynamic Handling Full page refresh in background on revalidate Dynamic holes streamed in parallel via Suspense (no full refresh)
Freshness Mechanism Time-based or on-demand revalidation of whole page Dynamic parts always fresh (per-request); static shell can use cache/ISR-like revalidation
Initial Load Fast (stale-while-revalidate) Extremely fast shell + progressive streaming
Use When Content changes periodically but whole page should stay consistent Page has mostly static structure + scattered dynamic/personalized elements
Complexity Simpler (export const revalidate = 60;) Requires Suspense boundaries and careful static/dynamic separation
Build/Regen Impact Regenerates full page in background Static shell regen possible (via cache config); dynamic is runtime

PPR can be seen as an evolution/enhancement over ISR for more granular hybrid rendering, especially in modern Next.js apps using React Server Components and streaming. ISR remains excellent for simpler per-page freshness without needing to split components.

1.6 Hybrid & Composed Rendering (Current Standard)

Different parts of the same application use different strategies:

  • Some pages fully static (SSG)
  • Some use ISR
  • Some use full SSR
  • Some are client-only interactive islands
  • Streaming, partial hydration, server components, and PPR are combined

The goal is to apply the lowest-cost, highest-performance strategy to each piece of content.

2. Build Process & CI/CD

Build Process Overview

Source code written for developer convenience is transformed into artifacts suitable for browsers and servers.

Main stages

  • Lock and install exact dependency versions
  • Transpile modern syntax to widely supported formats
  • Bundle modules and enable code splitting
  • Remove unused code (tree-shaking)
  • Minify scripts, styles, and assets
  • Optimize images, fonts, and other resources
  • Produce final output (static folder or server bundle)
  • Run validation (types, linting, tests)

Modern optimizations: Partial / Selective / Incremental Builds
Many contemporary toolchains and frameworks avoid full rebuilds on every change:

  • Incremental compilation (Turbopack, esbuild, SWC, Vite, Bun) — rebuilds only changed files/modules
  • Selective builds in monorepos (Nx, Turborepo, Lage, Bazel) — detect affected projects/packages and build/test/deploy only what’s changed
  • Partial rebuilds in static/hybrid frameworks (Next.js ISR/PPR-aware builds, Astro incremental content, Qwik resumability) — regenerate only stale or modified routes/sections

This drastically reduces build times (especially in large codebases), lowers CI costs, and enables faster feedback loops and safer deploys. These optimizations pair particularly well with ISR (selective page regen) and PPR (static shell + dynamic runtime).

ISR vs Partial/Selective Builds

Incremental Static Regeneration (ISR) and Partial/Selective Builds both aim to avoid full rebuilds of an entire site when only some content changes. However, they represent different approaches, especially in the context of Next.js (the most common framework where these terms appear).

Core Concepts

Incremental Static Regeneration (ISR)

  • A runtime + caching feature in Next.js.
  • Pages are generated statically (like SSG), but you can update individual pages after deployment without redeploying or rebuilding the whole site.
  • Two main flavors exist:
    • Time-based ISR — Pages regenerate in the background after a set interval (e.g., revalidate: 60 seconds) using “stale-while-revalidate”.
    • On-demand ISR — Manually trigger regeneration for specific pages/paths/tags (via webhooks, API routes calling revalidatePath() or revalidateTag()).
  • Key benefit: Extremely fast edge-cached delivery + freshness without full rebuilds.

Partial / Selective Builds

  • This usually refers to build-time incremental behavior — only rebuilding/changing the parts of the site that actually changed (e.g., new or modified pages).
  • In pure static site generators (Hugo, Gatsby, Eleventy, Astro), this is often called “incremental builds” or “partial rebuilds”.
  • In Next.js (especially older versions or Pages Router with very large sites), people sometimes wished for true build-time incremental SSG (only build changed pages during next build).
  • However, Next.js traditionally does full builds → the closest built-in solutions are ISR (for runtime updates) or Partial Prerendering (PPR) for fine-grained static + dynamic handling.

Quick Comparison Table

Aspect ISR (Runtime-focused) Partial/Selective Builds (Build-time focused)
When it happens After deployment, on request or schedule During next build / CI deploy
Scope Individual pages regenerated in background Only changed files/modules/routes rebuilt
Requires server? Yes (needs runtime to revalidate) No (pure static output)
Best for Content freshness without redeploy (blogs, catalogs) Faster CI/builds in large static/hybrid sites
Next.js native? Yes (built-in via revalidate, revalidateTag) Partial via tools like Turbopack/Nx; not full native SSG incremental
Trade-off Low runtime cost, but needs edge/serverless support Faster builds, but content updates still need redeploy

In practice: Use ISR/PPR for dynamic-ish static content (no redeploy needed for updates). Use partial/selective build tools (Turborepo, Nx, Turbopack) to speed up the actual build/deploy step when code or config changes.

Continuous Integration (CI)

Every code change triggers an automated pipeline that verifies the project remains healthy.

Typical checks

  • Successful compilation/transpilation
  • Type consistency
  • Code style enforcement
  • Unit and integration test passage
  • Successful production build
  • Basic security and vulnerability scans

With selective/partial strategies, only impacted tests/builds run → significantly faster CI (critical for monorepos or large teams).

Goal: detect problems immediately after a commit, before they affect others.

Continuous Delivery / Deployment (CD)

Once CI passes, the validated build is automatically (or semi-automatically) moved toward production.
Modern platforms often provide:

  • Preview environments per branch/pull request
  • Atomic deployments
  • Rollback capability
  • Traffic shifting between versions

Selective/partial deploys further optimize by pushing only changed artifacts (via edge functions, ISR revalidation, differential bundles, or PPR streaming).

Goal: make releasing software fast, safe, repeatable, and low-risk.

REFERENCE LIST

There is no related material added for this note.


Here are all the notes in this garden, along with their links, visualized as a graph.