fix: revalidate stable-named build assets - #126
Conversation
Only fingerprinted /build outputs (name-XXXXXXXX.ext) keep the four-hour lifetime. Every other build asset, including CSS and custom entry points with stable filenames, now gets the same ETag revalidation as main.js so a deployment cannot pair new HTML and JavaScript with a stale stylesheet. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Every negative fixture was hyphen-free, so four widening mutations of FINGERPRINTED_BUILD_ASSET passed the suite; the one that treats any hyphenated stem as a hash would have served a stable theme-dark.css for four hours. Adds hyphenated names that are not esbuild hashes, proves the ETag tracks content, corrects the override example to match source maps, and documents the one filename shape the heuristic misreads. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
test: pin what the fingerprint rule rejects — adversarial review found the discriminating half of Added negatives that are hyphenated but not esbuild hashes ( Also from the review: the 304 test now proves the ETag tracks content (rewrite the file, replay the old validator, expect 200 and the new body) rather than only that a matching validator returns 304. The override example in the static-files guide used One item is a judgement call rather than a fix, left for you: the rule is a filename heuristic, so a stable entry point whose stem ends in eight uppercase alphanumerics (
|
## [0.11.5](0.11.4...0.11.5) (2026-09-11) ### Bug Fixes * revalidate stable-named build assets ([#126](#126)) ([89a3466](89a3466))
|
🎉 This PR is included in version 0.11.5 🎉 The release is available on: Your semantic-release bot 📦🚀 |
Summary
Juniper served every
/build/*file other thanmain.jswithpublic, max-age=14400, including CSS entry points whose filenames never change. After a deployment a browser could pair new HTML and JavaScript with a stylesheet from the previous build for up to four hours. The cache policy is now keyed on whether the filename is fingerprinted: esbuild'sname-XXXXXXXX.extoutputs (and their source maps) keep the four-hour lifetime, and every other build asset gets the sameprivate, no-cache, must-revalidate, max-age=0plus ETag treatmentmain.jsalready had.Changes
src/server.tsx: one/build/*middleware that applies long-lived caching only to fingerprinted names and ETag revalidation to everything else (main.js,main.css, custom entry points such asstyles/theme.cssorworkers/sw.js, and their source maps).src/server.test.tsx: coverage formain.css, nested stable entry points and source maps, fingerprinted JS/CSS/map/route chunks keepingpublic, max-age=14400with no ETag, and a conditional request round trip (If-None-Match→ 304 with headers retained, mismatch → 200 with body).docs/static-files.md,docs/styling.md,docs/deployment.md: state the actual defaults, drop the per-app ETag middleware recipe the framework now covers, add a migration section for URLs browsers already cached under the old policy (change the asset URL once), and note that CDN settings can override origin headers so verification belongs on the public custom domain.Testing
deno task checkanddeno task test --parallel --reporter=dotgreen (33 files, 385 steps).Cache-ControlandETagassertions; the fingerprinted-asset test stays green on both.Closes
Closes #125
🤖 Generated with Claude Code