Repository navigation
Bust caches for unhashed assets so deploys don't break the widgets - #20
Merged
Merged
Conversation
Behind a CDN, browsers kept a stale js/main.js that imported chunks from the previous release, which no longer exist, so the interactive widgets silently failed after a deploy. The page now appends a content fingerprint of static/ to styles.css, htmx.min.js and js/main.js. Hashed bundler chunks are served as immutable, everything else as no-cache with an ETag, and the HTML as no-cache. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Hwr9dH2APEpeX6fBPghR5g
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
After deploying 0.1.3, the interactive widgets (Chaos Monkey, terminal, load balancing, live manifests) did nothing on patrick.laabs.dev, although they work locally. The only console message was a report-only CSP notice about loading
chaos-SXNL27HD.js.script-src 'unsafe-inline' 'unsafe-eval') does not come from the blog; something in front of the cluster adds it. Report-only policies never block anything.chaos-SXNL27HD.jsis the chunk from 0.1.2; in 0.1.3 it ischaos-EYWIP36I.js. The browser was running a cachedjs/main.jsfrom the previous release that imports chunks which no longer exist.Cache-Controland no validators for static files. Embedded files have no modification time, so there was noLast-Modifiedand noETageither. A CDN such as Cloudflare then applies its default browser TTL (4h), so a new HTML page ran against an oldmain.js.Fix
Cache busting:
index.htmlappends?v=<fingerprint>tostyles.css,htmx.min.jsandjs/main.js. The fingerprint is a SHA-256 over everything understatic/, computed once at startup (per request in-dev). A new release therefore always loads its own entry script.Cache headers:
*-XXXXXXXX.js)Cache-Control: public, max-age=31536000, immutable; the name changes whenever the content doesCache-Control: no-cacheplusETag: "<fingerprint>", so caches revalidate cheaply (304)Cache-Control: no-cache-devCache-Control: no-storeTesting
go vet ./...andgo buildpass.curlchecks:…/main.js?v=b1f21eb1ae77(likewise for the CSS and htmx);main.jsis served withno-cacheand the ETag, andIf-None-Matchreturns304;chaos-EYWIP36I.jsis served withimmutable;-devserves static files withno-store.main.js?v=…, and the Chaos Monkey boots, heals, scales and runs the monkey as before.After deploying: one hard reload (or purging the CDN cache) clears the stale
main.jsthat browsers already hold. Future deploys won't need it.Generated by Claude Code