From cec2b2dd9924338bdcf23d4007a034ef9e3c1ef4 Mon Sep 17 00:00:00 2001 From: Chris Amico Date: Thu, 3 Oct 2024 09:49:46 -0400 Subject: [PATCH 1/4] Add a basic service worker to cache requests --- src/service-worker.ts | 86 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 src/service-worker.ts diff --git a/src/service-worker.ts b/src/service-worker.ts new file mode 100644 index 000000000..aa169f42a --- /dev/null +++ b/src/service-worker.ts @@ -0,0 +1,86 @@ +/// +/// +/// +/// + +const sw = self as unknown as ServiceWorkerGlobalScope; + +import { build, files, version } from "$service-worker"; + +// 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); + } + + 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 adc822a4f92f0d1f37db1727d1a83025b32d1d4a Mon Sep 17 00:00:00 2001 From: Chris Amico Date: Thu, 3 Oct 2024 11:24:12 -0400 Subject: [PATCH 2/4] Handle updates --- src/routes/+layout.svelte | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index eb28d97ef..63d9e5321 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -1,5 +1,8 @@ @@ -16,4 +32,6 @@ {/if} + + From 01873e1816c2fa8b1cd9c760875cd1a4492b7923 Mon Sep 17 00:00:00 2001 From: Chris Amico Date: Thu, 3 Oct 2024 11:44:58 -0400 Subject: [PATCH 3/4] Trying to make typescript shut up about a custom window event --- src/app.d.ts | 10 ++++++++++ src/routes/+layout.svelte | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/app.d.ts b/src/app.d.ts index ede601ab9..a6cb12cf6 100644 --- a/src/app.d.ts +++ b/src/app.d.ts @@ -8,6 +8,16 @@ declare global { // interface PageState {} // interface Platform {} } + + namespace svelteHTML { + interface HTMLAttributes { + "on:vite:preloadError"?: (event: any) => any; + } + + interface HTMLProps { + "on:vite:preloadError"?: (event: any) => any; + } + } } export {}; diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 63d9e5321..5e1c1630c 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -1,4 +1,4 @@ -