HTML Parsing & Script Loading

Bytes to tokens to a tree, streaming as it arrives — and what `script`, `defer`, `async` and `type=module` actually do to that stream.

The HTML Tokenizer
▶ lab

Bytes become characters become tokens, through a specified state machine that has no fatal errors and that the tree builder can reach in and reconfigure.

Q · How does a stream of bytes become the start tags, attributes and text the browser works with — and why does malformed HTML never throw?
Tree Construction
▶ lab

Tokens become a DOM through insertion modes and a stack of open elements — which is why the tree the browser built is frequently not the markup you wrote.

Q · Why is the DOM in the Elements panel different from the HTML I sent, and what rules produced the difference?
Streaming HTML
▶ lab

The parser starts on the first chunk and never waits for the last one — which makes time to first byte, flush behaviour and document order performance decisions rather than server details.

Q · If the browser parses HTML as it arrives, what does that change about how I should generate and send it?
Why a Script Tag Stops the Parser
▶ lab

A classic `<script>` suspends tree construction because the script may write into the document at that exact point — and it also waits for pending stylesheets it may never touch.

Q · What exactly happens when the parser reaches a `<script>` tag, and why does the page go quiet?
`defer`, `async` and `type="module"`
▶ lab

Three genuinely different orderings: `defer` keeps document order and runs before DOMContentLoaded, `async` runs whenever it arrives with no order guarantee, and modules are deferred by default.

Q · Which script-loading attribute should this tag have, and what ordering guarantee am I actually getting?
The Preload Scanner
▶ lab

A second, lightweight reader runs ahead of the real parser looking for URLs to fetch — and almost every modern loading pattern accidentally hides resources from it.

Q · If a script stops the parser, how does the browser keep discovering images and stylesheets further down the document — and why does that stop working in my app?