Tokeniser
The state machine that turns the HTML byte stream into tokens: start tags, end tags, attributes, text and comments.
in practiceWhy a stray "<" in text or an unclosed attribute quote swallows the rest of a page.
From bytes to a DOM and from source to running code: tokenising, tree construction, the scripts and stylesheets that block, lifecycle events, JS compilation and hydration.
The terms between the first byte of HTML and a document the browser can style: encoding, tokens, the tree, and the scripts and stylesheets that stop the parser.
The state machine that turns the HTML byte stream into tokens: start tags, end tags, attributes, text and comments.
in practiceWhy a stray "<" in text or an unclosed attribute quote swallows the rest of a page.
The stage that takes tokens and builds the DOM, applying the HTML spec's error recovery so malformed markup still produces a tree.
in practiceWhy a <div> inside a <p> closes the paragraph, and the Elements panel shows a tree different from your source.
The Document Object Model: the live tree of nodes the parser builds and scripts read and change; the page's structure in memory.
in practicedocument.querySelector, the Elements panel, every framework's render target.
How bytes map to characters; the parser must know it (UTF-8 by default, from the header or a meta charset in the first 1024 bytes) before it can read text.
in practiceMojibake ("é" for "é") when a server sends the wrong charset; meta charset first in head.
A classic script without async or defer: the HTML parser stops, fetches and runs it, then continues, because the script might call document.write.
in practiceA long white screen while a third-party script in head downloads; the Performance panel's "Parse HTML" gap.
Both fetch in parallel with parsing; async runs as soon as it arrives (any order), defer runs after parsing finishes, in document order.
in practicedefer for app code that needs the DOM; async for independent scripts like analytics; type=module is deferred by default.
A secondary lightweight parser that looks ahead in the HTML for resource URLs and starts fetching them while the main parser is blocked.
in practiceWhy resources in markup load fast and ones injected by script or set in CSS backgrounds load late.
Stylesheets in head block first render: the browser will not paint until it has the CSSOM, to avoid a flash of unstyled content.
in practiceThe "Render-blocking requests" Lighthouse audit; why critical CSS is inlined and the rest loaded later.
The event fired when the HTML is fully parsed and deferred scripts have run; images and iframes may still be loading.
in practiceThe blue line in the Network waterfall; the old place to start app code.
Fired when the page and all its subresources (images, iframes, stylesheets) have loaded.
in practiceThe red line in the waterfall; rarely the right signal for "ready" because lazy content keeps arriving after it.
loading, then interactive (parsed: DOMContentLoaded next), then complete (load next).
in practiceScripts that may run late check it before waiting for an event that already fired.
Continuing to tokenise and fetch ahead while a script runs, discarding the work if the script changes the document.
in practiceThe reason document.write is hostile to performance: it can invalidate the speculation.
The terms between a script's bytes and an interactive page: parse, compile, cache, modules and hydration.
Turning JS source into an abstract syntax tree; costs CPU in proportion to the source size, before any code runs.
in practiceThe "Compile Script" and "Parse" slices in a Performance trace; why 1 MB of JS is slower than 1 MB of images.
V8 only fully parses functions when they are first called; it preparses the rest just enough to find their boundaries and errors.
in practiceWhy wrapping a function in parentheses (PIFE) once hinted eager parsing; why unused code still costs a preparse.
Abstract syntax tree: the program as a tree of nodes (declarations, expressions, statements) that compilers, linters and bundlers all work on.
in practiceESLint rules, Babel and SWC transforms, codemods, the TypeScript compiler.
A compact instruction format V8's Ignition interpreter runs; generated from the AST, cached, and the input to the optimising compilers.
in practicenode --print-bytecode; code caching makes repeat visits skip parse and compile.
V8 storing compiled bytecode for a script so the next load skips parsing and compiling it.
in practiceFaster repeat visits for stable, hashed script URLs; service-worker-cached scripts get it eagerly.
Parsing a large object literal from a JSON.parse string is faster than from a JS object literal, because JSON's grammar is simpler.
in practiceLarge embedded state (initial data in a script tag) delivered as JSON rather than as JS.
The tree of ES module imports the browser must fetch, parse and link before any module code runs.
in practiceWaterfalls of module requests in dev servers; modulepreload to flatten them; bundlers flatten them in production.
Attaching a client framework's event handlers and state to server-rendered HTML, by rendering the same tree and adopting the existing DOM.
in practiceHydration mismatch warnings; the gap between seeing a button and it working; islands and partial hydration.
Sending the document in chunks as the server produces them, so the browser parses and renders the head and shell before the body is done.
in practiceReact renderToPipeableStream with Suspense boundaries; Transfer-Encoding: chunked.
A template with shadowrootmode in HTML that the parser turns into a shadow root, so web components render server-side without JS.
in practiceSSR for web components; style encapsulation without a script.
A legacy rendering mode triggered by a missing or old doctype, in which layout follows pre-standards bugs.
in practiceOdd box sizing and table layout bugs in emails and old pages; always start with <!doctype html>.
Assigning a string to innerHTML runs the HTML parser on it in fragment mode and replaces the element's children.
in practiceAn XSS sink (see Security); slower than DOM APIs for small changes; scripts inserted this way do not run.