CONCEPT Cited by 1 source
Bundler chunk invalidation¶
Bundler chunk invalidation is the phenomenon where a small source-code change causes a JavaScript bundler (webpack, Vite, Rollup, esbuild, Turbopack, …) to re-chunk the application such that asset filenames change even when most of the content is unchanged. Every client's browser sees a new URL for the bundle, cache keys miss, and the full bundle is re-downloaded — even though 99 %+ of the bytes are identical to what the client already has cached.
Canonical framing: this is the root cause for why caching has "effectively opted out" in high-deploy-frequency production environments, and the motivating problem for shared-dictionary compression.
How the mechanism works¶
Modern JS bundlers emit assets with content-addressed filenames:
The hash suffix is computed from the chunk's contents (or, in some configurations, from the content + module graph). This is a deliberate cache-busting strategy: when the content changes, the filename changes, so the browser can't accidentally serve stale content from cache.
The problem: the hash changes for the whole chunk when
any byte in the chunk changes. A one-line fix in a single
module that happens to sit in the app.js chunk produces a
new app.a7b3c9f.js → app.e4f2d81.js filename, even though
99.9 % of the bytes are identical.
More aggressively: many bundlers re-chunk when the module graph shifts, not just when contents change. Adding or removing an import can redistribute modules across chunks, which rewrites every chunk's content, which rewrites every chunk's hash, which rewrites every filename.
Why this breaks caching¶
Standard HTTP caching is URL-keyed. A cached
app.a7b3c9f.js is dead the moment the deploy emits
app.e4f2d81.js — the client has no way to know the new URL
is almost the same as the old one. It fetches from scratch.
- High-deploy-frequency amplification: a team shipping ten deploys a day invalidates every client's bundle cache ten times a day. "Ship ten small changes a day, and you've effectively opted out of caching." (Source: this article)
- AI-assisted-development amplification: AI coding tools compress the interval between commits; CI/CD pipelines ship more frequently; effect compounds.
- Mandatory-upgrade amplification: security patches, dependency bumps, feature flags flipping all trigger re-chunks, not just intentional product changes.
Why traditional compression can't help¶
Per-response compression (gzip / Brotli / Zstandard) looks at
the bytes of the response in isolation. It has no memory of
what the client has cached. It compresses app.e4f2d81.js from
scratch as if the client had never seen anything before —
producing the same ~92 KB gzip output it did for
app.a7b3c9f.js, even though the actual new information is a
few KB of diff. "Traditional compression helps with the size
of each download, but it can't help with the redundancy. It
doesn't know the client already has 95 % of the file cached."
Why shared-dictionary compression fixes it¶
Shared-dictionary
compression + [[systems/rfc-9842-compression-dictionary-
transport|RFC 9842]] let the server compress the new version
against the previous cached version using the previous
response as the dictionary. Even though the URL has changed,
the browser still has the previous response cached under a
different URL; via Use-As-Dictionary: match=, the dictionary
applies to the new URL. Only the diff goes on the wire.
Result per Cloudflare's 2026-04 lab: - 272 KB bundle with a few localised changes → 2.6 KB DCZ (97 % over gzip). - 94 KB bundle with only a config block changed → ~159 bytes (99.5 % over gzip) — canicompress.com.
Seen in¶
- sources/2026-04-17-cloudflare-shared-dictionaries-compression-that-keeps-up-with-the-agent — bundler chunk invalidation is named as the canonical root cause shared-dictionary compression is designed to fix: "the bundler re-chunks, filenames change, and every user on earth could re-download the entire application. Not because the code is meaningfully any different, but because the browser/client has no way to know specifically what changed. It sees a new URL and starts from zero."