Module 00 intermediate 25 min

Foundations & Mental Model

Navigation lifecycle, critical rendering path, main thread, event loop, and perception budgets — the substrate everything else builds on.

You already know that “performance matters.” This module gives you the browser mental model experts use to reason about any metric — without re-explaining what HTTP is.

Every page load is a pipeline:

  1. Navigation start — user clicks, types URL, or SPA router fires pushState
  2. Connection — DNS, TCP, TLS (or QUIC for HTTP/3)
  3. Request/response — TTFB: time until first byte of HTML
  4. Parsing — HTML → DOM; CSS → CSSOM; JS may block parsing
  5. Render — render tree → layout → paint → composite
  6. Interaction — event listeners, hydration, long tasks compete for the main thread
Critical rendering path (simplified)
Navigation DNS TLS TTFB Parse HTML → DOM CSSOM Render tree Layout Paint FCP · LCP markers along this timeline →

Critical rendering path (CRP)

The CRP is the minimum work to show pixels:

StageWhat happensPerf lever
DOMHTML parsed to nodesMinimize blocking scripts in <head>
CSSOMCSS parsed, selectors matchedSplit non-critical CSS; avoid @import chains
Render treeDOM + computed styles (visible nodes)display:none subtrees excluded
LayoutBox geometry calculatedAvoid forced sync layout in hot paths
PaintPixels drawn into layersPrefer compositor-only properties
CompositeLayers GPU-compositedtransform / opacity are cheap

DO inline critical above-the-fold CSS and defer the rest.

DO use defer or type="module" for non-critical scripts.

DON’T put large synchronous scripts in <head> — they halt DOM construction.

<style>
  /* Critical: hero + header only */
  .hero { min-height: 60vh; }
</style>
<link rel="preload" href="/styles/main.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<script type="module" src="/app.js"></script>

Main thread & event loop

JavaScript runs on the main thread alongside rendering. The event loop processes:

  1. MacrotaskssetTimeout, I/O callbacks, user events
  2. MicrotasksPromise.then, queueMicrotask (drain completely before next macrotask)
  3. Render steps — style, layout, paint (if needed)
Task → microtasks → render (repeat)
Task μtasks Render Task Long task (>50ms) blocks input until yield or completion

A long task is any task > 50 ms. Long tasks block input handling and push INP/TBT up. The fix is not “faster JS” alone — it’s yielding so the browser can respond.

Event loop visualizer

Tasks (dark), microtasks (green), render (teal) appear in order.

RAIL & perception budgets

Google’s RAIL model (Response, Animation, Idle, Load) translates to budgets:

ConcernTarget
Input response< 100 ms perceived
Animation frame< 16 ms (60 fps)
Idle work chunks< 50 ms
Meaningful paint< 1 s perceived (context-dependent)

Users forgive slower loads more than janky interactions — optimize responsiveness on interactive pages first.

Resource hint mental model

HintUse when
preconnectYou know the origin (fonts, API) — saves RTT on TLS
dns-prefetchCheaper fallback for third parties
preloadSame-origin asset needed now for this navigation
prefetchAsset for likely next navigation
modulepreloadES module graph for current page

Mental model: Preconnect for domains, preload for viewport-critical assets, prefetch for futures.

What to learn next

Module 01 maps these pipeline stages to measurable metrics (FCP, LCP, INP, CLS). Module 02–05 show how to move each needle. Module 06 teaches measurement; Module 07 covers speculation rules, bfcache, and streaming.

Live on this page

TTFB
FCP
LCP
INP
CLS