diff --git a/public/sw.js b/public/sw.js index b747c319..d27bb301 100644 --- a/public/sw.js +++ b/public/sw.js @@ -1,5 +1,10 @@ -const CACHE = "atom-v3"; -const API_CACHE = "atom-api-v3"; +// Bumped to v4. The v3 worker cached /_next/static/ and /assets/ cache-first +// under a hardcoded cache name that was not tied to the build, so a release +// left the browser replaying the previous release's chunks against the new +// HTML. That combination renders a blank page. The cache name is the version, +// so it must move whenever this behaviour changes. +const CACHE = "atom-v4"; +const API_CACHE = "atom-api-v4"; self.addEventListener("install", () => self.skipWaiting()); @@ -18,31 +23,32 @@ self.addEventListener("activate", (event) => { ); }); +// Static build output is NOT cached here on purpose. +// +// nginx already sends `/_next/static/` and `/assets/` with +// `max-age=31536000, immutable`. Those filenames are content-hashed, so the +// HTTP cache is both sufficient and safe: a changed file gets a new name. +// Wrapping them in a Cache Storage entry bought nothing and introduced a +// staleness bug the HTTP cache cannot have — the cache name had no build id, +// so a release kept serving the previous release's chunks. +// +// Letting these requests fall through also means a failed fetch surfaces as a +// normal network error the browser can retry, instead of a rejected +// respondWith() that silently drops the