From 4d36db90f12090fcc4200f341f9559267346c496 Mon Sep 17 00:00:00 2001 From: m17hr1l Date: Mon, 25 May 2026 17:36:08 +0200 Subject: [PATCH] =?UTF-8?q?stage-30=20fix:=20SW=20cache=20strategy=20?= =?UTF-8?q?=E2=80=94=20bump=20version=20+=20stale-while-revalidate?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit User reported mobile nav still looked unresponsive. Verified the new nav-toggle CSS and markup are deployed; the browser's service worker was serving the prior cockpit.css cache-first from psyc-v1. Two fixes so this can't recur: - CACHE_VERSION bumped to psyc-v2 → the activate handler now wipes the v1 cache on the user's next visit. - Static-asset strategy changed from cache-first to stale-while-revalidate: serve from cache for instant render, then refresh in the background so the *next* load picks up the new CSS/JS with no manual cache-busting. Falls back to network if cold. Co-Authored-By: Claude Opus 4.7 --- src/psyc/cockpit/static/sw.js | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/psyc/cockpit/static/sw.js b/src/psyc/cockpit/static/sw.js index a391d29..e0b3570 100644 --- a/src/psyc/cockpit/static/sw.js +++ b/src/psyc/cockpit/static/sw.js @@ -5,7 +5,7 @@ // This makes the cockpit installable as a PWA and survives flaky connections, // without serving stale operational data behind the operator's back. -const CACHE_VERSION = "psyc-v1"; +const CACHE_VERSION = "psyc-v2"; const STATIC_ASSETS = [ "/static/cockpit.css", "/static/psyc-tokens.css", @@ -39,13 +39,19 @@ self.addEventListener("fetch", (event) => { const req = event.request; if (req.method !== "GET") return; if (isStatic(req)) { - // cache-first + // stale-while-revalidate: serve from cache for speed, refresh in the + // background so subsequent loads pick up new CSS/JS without a manual + // version bump. Falls back to network if the cache is cold. event.respondWith( - caches.match(req).then((hit) => hit || fetch(req).then((resp) => { - const copy = resp.clone(); - caches.open(CACHE_VERSION).then((c) => c.put(req, copy)).catch(() => {}); - return resp; - })) + caches.open(CACHE_VERSION).then((cache) => + cache.match(req).then((hit) => { + const network = fetch(req).then((resp) => { + if (resp && resp.ok) cache.put(req, resp.clone()).catch(() => {}); + return resp; + }).catch(() => hit); + return hit || network; + }) + ) ); } else { // network-first for HTML + API