Skip to content

feat: robust cache busting on deployment#33

Open
devin-ai-integration[bot] wants to merge 1 commit into
mainfrom
devin/1781874500-cache-busting
Open

feat: robust cache busting on deployment#33
devin-ai-integration[bot] wants to merge 1 commit into
mainfrom
devin/1781874500-cache-busting

Conversation

@devin-ai-integration

Copy link
Copy Markdown
Contributor

Summary

Prevents stale index.html / service worker from being served after deployment. Vite already content-hashes JS/CSS chunks, but the HTML shell and SW can get cached by the browser or APISIX gateway — causing users to load old bundles.

Three-layer defense:

  1. Express (server-side)serveStatic() and the SPA fallback now set:

    Cache-Control: no-cache, no-store, must-revalidate
    Pragma: no-cache
    Expires: 0
    

    on *.html, sw.js, manifest.json. Hashed assets (/assets/*) get max-age=1y, immutable.

  2. Service Worker (client-side) — On activate, the SW now purges all caches not matching the current CACHE_VERSION, logs each purge, and posts SW_VERSION_CHANGED to open clients. main.tsx registers the SW with updateViaCache: "none", polls reg.update() every 30 min, and auto-reloads the page when a new SW activates.

  3. APISIX (gateway-level) — New routes for /, /sw.js, /manifest.json with response-rewrite setting no-cache headers. /assets/* gets immutable 1yr cache.

Also adds <meta http-equiv="Cache-Control" ...> tags to index.html as a belt-and-suspenders fallback for browsers that respect them.

Link to Devin session: https://app.devin.ai/sessions/3ebd42bf0430422a9a2bd85ed9f9cd4c
Requested by: @munisp

- Express: Cache-Control no-cache/no-store/must-revalidate for index.html,
  sw.js, manifest.json; immutable 1yr cache for hashed assets
- HTML: meta http-equiv tags to prevent browser caching of entry point
- Service Worker: version-based cache purge on activate, notifies clients
  of version change, updateViaCache: none on registration
- main.tsx: SW registration with update detection, 30min update polling,
  auto-reload on new version activation
- APISIX: route-level cache headers — no-cache for /, /sw.js, /manifest.json;
  immutable 1yr for /assets/*

Co-Authored-By: Patrick Munis <pmunis@gmail.com>
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author
Original prompt from Patrick

https://drive.google.com/file/d/1ko3y7OBp1tJIXGTbe2QGFRHMQfxMTWHX/view?usp=sharing

  1. Extract ALL everything in the archive
  2. how do ensure and assess that features for example domain and business logic/rules/requirements are fully impemented and production ready and complete - can you thoroughly assess each files and features to determine there are ready for production
  1. Database integration (replace in-memory with real Postgres)
  2. Inter-service HTTP wiring with retries/circuit breakers
  3. Security hardening (JWT everywhere, remove hardcoded creds, mTLS)
  4. Integration tests for critical flows
  5. Graceful shutdown, observability, alerting
    3)search for orphan, partially and generic scaffolded features across the platform - fully implement them end to end -generic CRUD-only patterns , modules with no domain logic, disconnected features, and incomplete implementations.

@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@devin-ai-integration devin-ai-integration Bot changed the base branch from production-hardened to main June 19, 2026 13:13
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

Test Results: Cache Busting on Deployment

Tested by running a production-mode Express server (identical serveStatic() logic) serving dist/public/, verifying HTTP headers via curl + source code inspection.

Cache Header Tests (5/5 passed)
# Test Result Evidence
1 GET / returns no-cache headers PASSED Cache-Control: no-cache, no-store, must-revalidate, Pragma: no-cache, Expires: 0
2 SPA fallback (/some-random-route) returns no-cache PASSED Same three headers on fallback route
3 GET /sw.js returns no-cache headers PASSED Cache-Control: no-cache, no-store, must-revalidate (Content-Type: application/javascript)
4 GET /manifest.json returns no-cache headers PASSED Cache-Control: no-cache, no-store, must-revalidate (Content-Type: application/json)
5 Hashed asset (/assets/*.js) returns immutable cache PASSED Cache-Control: public, max-age=31536000, immutable
Source Code Verification (5/5 passed)
# Test Result
6 HTML meta tags in index.html PASSEDCache-Control, Pragma, Expires meta tags present
7 SW CACHE_VERSION = "v6" PASSED
8 SW activate purges all non-matching caches PASSED — uses Set allowlist instead of prefix filter
9 main.tsx updateViaCache: "none" PASSED
10 APISIX routes have cache-control config PASSED — 4 routes with correct headers
Not Tested
  • APISIX live header injection (no APISIX instance locally)
  • SW lifecycle in real browser (full production server requires 13 env secrets)
  • 30-min SW update polling (timing-dependent)

Devin session

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants