From cd725077669f962a8f5a62b3e981259d105a1c4f Mon Sep 17 00:00:00 2001 From: Hermes Date: Tue, 18 Aug 2026 10:52:49 +0200 Subject: [PATCH] =?UTF-8?q?fix(pwa):=20purge=20stale=20caches=20from=20app?= =?UTF-8?q?=20startup=20=E2=80=94=20clear=20construction-delivery-*=20cach?= =?UTF-8?q?es=20directly=20in=20page=20context,=20independent=20of=20SW=20?= =?UTF-8?q?update?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - new src/utils/pwaCacheCleanup.js: deletes all construction-delivery-* caches except current v115 on every app load; runs in page context so it works even for users still on old SW - wire into main.jsx startup - fixes 3GB cache bloat / 30-40s hangs for users whose SW hasn't updated --- src/main.jsx | 4 ++++ src/utils/pwaCacheCleanup.js | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 src/utils/pwaCacheCleanup.js diff --git a/src/main.jsx b/src/main.jsx index 391bef8..8c23890 100644 --- a/src/main.jsx +++ b/src/main.jsx @@ -8,11 +8,15 @@ import { FontSettingsProvider } from "./context/FontSettingsContext"; import ErrorBoundary from "./components/ErrorBoundary"; import { initErrorLogging } from "./utils/errorLogger"; import { registerPwaServiceWorker } from "./hooks/usePwaStatus"; +import { clearStalePwaCaches } from "./utils/pwaCacheCleanup"; import "./index.css"; import "./styles/fontSettings.css"; registerPwaServiceWorker(); initErrorLogging(); +// Purge stale PWA caches on every startup so bloated caches (up to 3GB from old +// SW versions) are cleared even if the SW hasn't updated yet. +clearStalePwaCaches(); ReactDOM.createRoot(document.getElementById("root")).render( diff --git a/src/utils/pwaCacheCleanup.js b/src/utils/pwaCacheCleanup.js new file mode 100644 index 0000000..18e9f35 --- /dev/null +++ b/src/utils/pwaCacheCleanup.js @@ -0,0 +1,34 @@ +// Clears stale PWA caches directly from the page context, independent of the +// service worker. Runs on every app startup so that even users whose SW has not +// yet updated to the version with the fixed `activate` handler get their bloated +// (3GB) caches purged. Safe to run repeatedly: only `construction-delivery-*` +// caches are removed; nothing else is touched. +export const clearStalePwaCaches = async () => { + if (typeof caches === "undefined" || !("caches" in window)) { + return; + } + + try { + const keys = await caches.keys(); + const staleKeys = keys.filter( + (key) => + key.startsWith("construction-delivery-") && + // Keep only the current cache versions we ship with (v115). Any other + // version is stale and free to purge. + !["construction-delivery-static-v115", "construction-delivery-runtime-v115"].includes(key), + ); + if (staleKeys.length === 0) return; + + // Delete old caches first so the SW activation has less to scan next time. + await Promise.all(staleKeys.map((key) => caches.delete(key))); + + // Kick the service worker to re-run its activate handler (which also prunes + // caches and reclaims control) now that old caches are gone. + if ("serviceWorker" in navigator && navigator.serviceWorker?.controller) { + navigator.serviceWorker.controller.postMessage({ type: "CLEAR_STALE_CACHES" }); + } + } catch (err) { + // Best-effort cleanup — never block app startup on cache errors. + console.warn("[pwa] cache cleanup skipped:", err); + } +};