diff --git a/frontend/src/service-worker.js b/frontend/src/service-worker.js index 1d3c15c..0f233e7 100644 --- a/frontend/src/service-worker.js +++ b/frontend/src/service-worker.js @@ -40,17 +40,23 @@ function isMutablePath(p) { self.addEventListener('install', (event) => { // Best-effort: grab the app shell as an offline fallback. No bulk precache. - event.waitUntil( - caches.open(CACHE).then((c) => c.add('/').catch(() => {})).then(() => self.skipWaiting()) - ); + // Deliberately NO skipWaiting(): a new worker installs quietly and waits, so + // it never seizes a page that's mid-boot. It takes control on the next + // navigation, when the old worker has no clients — the post-deploy first-load + // then completes under the stable old worker (with its cache intact) against + // the warmed edge, instead of having its cache yanked mid-load. + event.waitUntil(caches.open(CACHE).then((c) => c.add('/').catch(() => {}))); }); self.addEventListener('activate', (event) => { + // Runs only when this worker actually activates (next navigation, never + // mid-boot), so deleting old version caches here is safe — and old immutable + // chunks live on at the origin for a 14-day grace window regardless. No + // clients.claim(): pages adopt this worker on their own next navigation. event.waitUntil( caches .keys() .then((keys) => Promise.all(keys.filter((k) => k !== CACHE).map((k) => caches.delete(k)))) - .then(() => self.clients.claim()) ); });