From 1b2eace73249a6ad8a294b6dd24348aa555df39f Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Tue, 22 Apr 2025 16:19:23 +0200 Subject: [PATCH 1/2] fix: remove service worker and adjust nginx caching --- docker/nginx.conf | 13 ++---- src/routes/+layout.svelte | 7 +++ src/service-worker.ts | 90 --------------------------------------- 3 files changed, 11 insertions(+), 99 deletions(-) delete mode 100644 src/service-worker.ts diff --git a/docker/nginx.conf b/docker/nginx.conf index 7f7313e00..d5c0efadb 100644 --- a/docker/nginx.conf +++ b/docker/nginx.conf @@ -1,8 +1,6 @@ -map $sent_http_content_type $expires { - # cache everything for 1 year - default 1y; - # html files shouldn't be cached for single-page applications - text/html off; +map $sent_http_content_type $cc_header { + default "public, max-age=31536000"; + text/html "no-cache"; } server { @@ -17,10 +15,7 @@ server { index index.html index.htm; try_files $uri /console/index.html; - # Add cache headers - expires $expires; - add_header Pragma public; - add_header Cache-Control "public"; + add_header Cache-Control $cc_header always; # Deny IE browsers from going into quirks mode add_header X-UA-Compatible "IE=Edge"; diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 169d2bb37..cd9071438 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -15,6 +15,13 @@ import { loading } from '$routes/store'; onMount(async () => { + // unregister all service-workers + if ('serviceWorker' in navigator) { + navigator.serviceWorker.getRegistrations().then((registrations) => { + registrations.forEach((registration) => registration.unregister()); + }); + } + // handle sources if (isCloud) { const urlParams = $page.url.searchParams; diff --git a/src/service-worker.ts b/src/service-worker.ts deleted file mode 100644 index b34bc0445..000000000 --- a/src/service-worker.ts +++ /dev/null @@ -1,90 +0,0 @@ -/// -/// -/// -/// - -import { build, files, version, base } from '$service-worker'; - -const sw = self as unknown as ServiceWorkerGlobalScope; - -// Create a unique cache name for this deployment -const CACHE = `cache-${version}`; - -const ASSETS = [ - ...build, // the app itself - ...files // everything in `static` -]; - -sw.addEventListener('install', (event) => { - // Create a new cache and add all files to it - async function addFilesToCache() { - const cache = await caches.open(CACHE); - await cache.addAll(ASSETS); - } - - // Check if the page URL does not match the exclusion path - const shouldCache = !location.pathname.startsWith(`${base}/auth`); - if (shouldCache) { - event.waitUntil(addFilesToCache()); - } -}); - -sw.addEventListener('activate', (event) => { - // Remove previous cached data from disk - async function deleteOldCaches() { - for (const key of await caches.keys()) { - if (key !== CACHE) await caches.delete(key); - } - } - - event.waitUntil(deleteOldCaches()); -}); - -sw.addEventListener('fetch', (event) => { - // ignore POST requests etc - if (event.request.method !== 'GET') return; - - async function respond() { - const url = new URL(event.request.url); - const cache = await caches.open(CACHE); - - // `build`/`files` can always be served from the cache - if (ASSETS.includes(url.pathname)) { - const response = await cache.match(url.pathname); - - if (response) { - return response; - } - } - - // for everything else, try the network first, but - // fall back to the cache if we're offline - try { - const response = await fetch(event.request); - - // if we're offline, fetch can return a value that is not a Response - // instead of throwing - and we can't pass this non-Response to respondWith - if (!(response instanceof Response)) { - throw new Error('invalid response from fetch'); - } - - if (response.status === 200) { - cache.put(event.request, response.clone()); - } - - return response; - } catch (err) { - const response = await cache.match(event.request); - - if (response) { - return response; - } - - // if there's no cache, then just error out - // as there is nothing we can do to respond to this request - throw err; - } - } - - event.respondWith(respond()); -}); From bef141729dbd19520b3967df510c8d178f6a3b54 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Tue, 22 Apr 2025 16:54:10 +0200 Subject: [PATCH 2/2] fix: service worker to preload assets using fetch --- src/routes/+layout.svelte | 7 ------- src/service-worker.ts | 25 +++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 7 deletions(-) create mode 100644 src/service-worker.ts diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index cd9071438..169d2bb37 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -15,13 +15,6 @@ import { loading } from '$routes/store'; onMount(async () => { - // unregister all service-workers - if ('serviceWorker' in navigator) { - navigator.serviceWorker.getRegistrations().then((registrations) => { - registrations.forEach((registration) => registration.unregister()); - }); - } - // handle sources if (isCloud) { const urlParams = $page.url.searchParams; diff --git a/src/service-worker.ts b/src/service-worker.ts new file mode 100644 index 000000000..23f5988aa --- /dev/null +++ b/src/service-worker.ts @@ -0,0 +1,25 @@ +/// +/// +/// +/// + +import { build, files } from '$service-worker'; + +const sw = self as unknown as ServiceWorkerGlobalScope; + +const ASSETS = [ + ...build, // the app itself + ...files // everything in `static` +]; + +// Preload all assets +sw.addEventListener('install', (event) => { + event.waitUntil(Promise.allSettled(ASSETS.map((asset) => fetch(asset)))); +}); + +// Clean up all old caches left by previous service workers +sw.addEventListener('activate', (event) => { + event.waitUntil( + caches.keys().then((keys) => Promise.all(keys.map((key) => caches.delete(key)))) + ); +});