fw-07 — Analysis

Required invariants

  1. The dependency graph is complete before any transform decision. Splitting and shaking are graph properties, not per-file ones.
  2. A cache key captures every input that affects the output — contents, resolved dependency hashes, config, plugin versions, env.
  3. Removal must preserve observable behaviour, which static analysis cannot prove in general.
  4. Every transform emits a source map, and the maps compose.

Why tree shaking is unsound without help

import './polyfill';            // side effect at module scope
window.registry.push(thing);    // side effect
export const unused = 1;

Removing the module because unused is unreferenced deletes the polyfill. The bundler cannot know those matter — and cannot know they don't. Hence "sideEffects": false: the author promising what the tool cannot derive.

A wrong promise produces a bundle missing code, with no error — the same silent-failure shape as a wrong patch flag (fw-06). Author assertions and compiler optimisations fail identically.

The cache-key table

KeyFails when
filenamecontents change
mtimetouched files; fresh checkouts; containers
content hasha dependency's content changed
content hash + dependency hashescorrect — needs the full graph
+ config, plugins, envcorrect in practice

This is the fourth appearance of caching-keyed-on-complete-inputs in the curriculum — after layout results, paint subsequences, and computed. The failure mode is identical every time: stale output, no error.

Code splitting costs that nobody counts

  • an extra round trip per chunk on the critical path,
  • runtime registry bookkeeping,
  • request waterfalls when chunk A discovers it needs chunk B,
  • cache coupling: a shared module's change invalidates every chunk containing it.

There is no configuration optimal for both first load and repeat-visit caching, which makes this a product decision informed by your traffic mix, not a best practice.

HMR's real requirement

Replaceability needs disposal: a module that registered a listener and does not clean up accumulates listeners on every hot update. That is fw-02's effect-cleanup problem at module granularity — any system that re-runs code must define what "undo the previous run" means, and the ones that skip that definition leak.