fw-07 — Analysis
Required invariants
- The dependency graph is complete before any transform decision. Splitting and shaking are graph properties, not per-file ones.
- A cache key captures every input that affects the output — contents, resolved dependency hashes, config, plugin versions, env.
- Removal must preserve observable behaviour, which static analysis cannot prove in general.
- 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
| Key | Fails when |
|---|---|
| filename | contents change |
| mtime | touched files; fresh checkouts; containers |
| content hash | a dependency's content changed |
| content hash + dependency hashes | correct — needs the full graph |
| + config, plugins, env | correct 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.