One small page
<link rel="stylesheet" href="styles.css">
<script src="legacy.js"></script>
<script defer src="app.js"></script><h1>Products</h1>
<button id="load-products">Load products</button>
<p id="status" role="status"></p>
<img src="hero.webp" alt="Featured products"
width="800" height="400">
<ul id="products"></ul>Use the full document in the chapter for the practical.
Navigation has setup costs
For https://shop.example.com/products?page=2:
- Resolve the destination if necessary.
- Establish or reuse a connection.
- Request the document.
- Begin processing available HTML.
Caches and restored pages can change this path. A small resource on a new origin may still incur setup cost.
Discovery can be the delay
<img src="hero.webp" alt="Featured products">versus a URL assigned only when JavaScript runs:
const image = new Image();
image.src = "hero.webp";Unless another reference reveals it earlier, the second request depends on script execution. Assigning src can start the request before insertion into the DOM.
Speculative discovery can look ahead
A preload scanner may inspect available markup while the main parser waits for a script.
It can find a later image or script reference.
It cannot execute arbitrary JavaScript to discover its future results or inspect bytes that have not arrived.
Do not assume a universal browser thread arrangement.
Choose script timing
For external scripts declared in the initial HTML:
| Mode | Main execution condition |
|---|---|
| Classic | Parser waits at the script |
| Defer | After parsing; ordered with deferred classic scripts |
| Async | When ready; document order not guaranteed |
| Module | Deferred by default; dependency graph applies |
async does not mean execution on a background thread.
CSS can delay a script too
<link rel="stylesheet" href="styles.css">
<script src="legacy.js"></script>A previously encountered stylesheet can block this script.
The parser is waiting for the script, so CSS can indirectly prolong the pause.
CSS blocking presentation and a script blocking parsing are different dependencies.
Readiness is not responsiveness
DOMContentLoaded: parsing and relevant deferred script processing have progressed to this milestone.- Window
load: additional load-delaying resources have completed. - Neither guarantees a particular paint time or fast future interactions.
Module experiments here omit imports and top-level await to keep the comparison focused.
Width and transform do different things
list.style.width = "320px";
list.style.transform = "translateX(20px)";Width can change wrapping and neighboring geometry.
A transform changes visual placement without reallocating normal-flow space.
Some transforms can reuse painted content. That is not a universal performance guarantee.
Why might “Working…” never appear?
Inside the click handler:
status.textContent = "Working…";
const start = performance.now();
while (performance.now() - start < 200) {
// Bounded demonstration only.
}
status.textContent = "Finished";Both DOM changes occur. The intermediate state may never reach the screen.
Microtasks are not background work
A microtask can queue another microtask.
The checkpoint keeps processing them, delaying later tasks if the chain grows.
Use the bounded chain in the chapter. Do not freeze the page with an endless loop.
Moving expensive work into a Promise callback does not make it free.
DevTools demonstration: discovery
- Serve the chapter’s small page over local HTTP.
- Record browser, cache, and throttling settings.
- Capture the image request from initial markup.
- Remove that reference; assign the same URL after a timer.
- Compare initiators and request start times in separate runs.
Explain differences; do not expect identical millisecond values.
DevTools demonstration: execution and rendering
- Record a click on the bounded slow handler.
- Locate its execution in a performance trace.
- Compare the DOM update with the visible result.
- Reset the page before comparing layout experiments.
A breakpoint changes timing. A console log proves execution, not paint.
Evidence before optimization
| Observation | Next question |
|---|---|
| Image request starts late | What revealed its URL? |
| Click response is delayed | What occupied the main thread? |
| Layout repeats | Are writes and geometry reads interleaved? |
| Trace looks different | Did cache, viewport, or throttling change? |
An unexplained trace is a reason to investigate, not to invent a guaranteed sequence.