fix: robust cache busting on deployment#80
Conversation
- Express: index.html served with no-cache/no-store headers; /assets/ immutable 1y - Service worker: version-based cache purge on activate; CACHE_BUSTED message to clients - HTML: meta http-equiv Cache-Control/Pragma/Expires tags prevent proxy caching - Nginx: split /assets/ (immutable) from HTML (no-cache); sw.js/manifest.json dedicated rules - Client: SW update listener auto-reloads tabs when new version deploys Co-Authored-By: Patrick Munis <pmunis@gmail.com>
Original prompt from Patrick
|
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
express.static intercepts / → index.html before the SPA fallback, so the setHeaders callback must also handle .html files to prevent 1-hour caching of the HTML entry point. Co-Authored-By: Patrick Munis <pmunis@gmail.com>
Cache Busting Test ResultsAll 7 tests passed. Tested by building the production bundle and serving it via a minimal Express server that replicates Express Response Header Tests
Built HTML Verification
Nginx Config VerificationBoth
Bug Found & Fixed During TestingIssue: Fix (commit |
Summary
After a deploy, browsers could serve stale
index.html(and therefore stale<script>tags pointing to old content-hashed chunks that no longer exist on the server), causing white-screen errors. This PR adds a 4-layer cache-busting strategy:Layer 1 — Express server (
server/_core/vite.ts):Key subtlety:
express.staticintercepts/→index.htmlbefore the SPA fallback fires, sosetHeadersmust handle.htmlfiles explicitly — without this,index.htmlwould be served withmax-age=3600.Layer 2 — Service worker (
client/public/sw.js):ndsep-v3; on activate, purges ALL caches not matching current versionCACHE_BUSTEDmessage to all open tabs → triggers reloadCLEAR_CACHESmessage from client for manual cache wipeLayer 3 — HTML meta tags (
client/index.html):<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate"><meta http-equiv="Pragma" content="no-cache"><meta http-equiv="Expires" content="0">Layer 4 — Nginx (
infra/nginx/nginx.conf+conf.d/locations.conf):/assets/→ immutable 1y (hashed Vite chunks)= /sw.js→ no-cache, no-store (must always be fresh)= /manifest.json→ no-cache, must-revalidate\.(png|jpg|...)$→ 1h with must-revalidate/(HTML fallback) → no-cache, no-store, must-revalidatelocations.conf)Link to Devin session: https://app.devin.ai/sessions/7b19b09de740454faef61082df9c86da
Requested by: @munisp