From cebd2ff3907bcb3f5270dc3ad8382869a83344c5 Mon Sep 17 00:00:00 2001 From: Mateusz Date: Thu, 30 Jul 2026 00:09:29 +0200 Subject: [PATCH] fix(pwa): auto-update service worker so clients receive new deploys MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The service worker never called skipWaiting()/clientsClaim() and VitePWA used the default "prompt" register mode with no prompt wired, so a new deploy stayed in the waiting state and open clients kept serving the old cached bundle indefinitely. This stranded users on stale frontends after a release (surfaced as a Firefox-only file-upload 500: a pre-#302 client posting multipart to the old /api/files route, which now expects a Content-Disposition header). Set registerType to autoUpdate and have the worker skip waiting and claim clients on activate, so a new build takes over and reloads open tabs. Uses the native SW APIs to avoid adding a workbox-core dependency. Note: only helps clients going forward — anyone already on the pre-fix worker must clear/unregister it once. --- app/src/sw.ts | 5 +++++ app/vite.config.ts | 1 + 2 files changed, 6 insertions(+) diff --git a/app/src/sw.ts b/app/src/sw.ts index 97edaa8a..80414ce3 100644 --- a/app/src/sw.ts +++ b/app/src/sw.ts @@ -12,6 +12,11 @@ if (files.length) { precacheAndRoute(files); navigationPreload.enable(); } + +self.skipWaiting(); +self.addEventListener("activate", (event) => { + event.waitUntil(self.clients.claim()); +}); /* const shareTargetHandler = async ({ event }) => { diff --git a/app/vite.config.ts b/app/vite.config.ts index 4956680c..5bef4e3b 100644 --- a/app/vite.config.ts +++ b/app/vite.config.ts @@ -47,6 +47,7 @@ export default defineConfig(({ command }) => ({ command === "serve" && basicSsl(), VitePWA({ injectRegister: "auto", + registerType: "autoUpdate", strategies: "injectManifest", srcDir: "./src", filename: "sw.ts",