137 lines
4.3 KiB
TypeScript
137 lines
4.3 KiB
TypeScript
/* eslint-disable no-var */
|
|
import { build, files, version } from '$service-worker';
|
|
|
|
// Code mostly comes from: https://dev.to/100lvlmaster/create-a-pwa-with-sveltekit-svelte-a36
|
|
// With some modifications done by someone in the comments
|
|
|
|
const worker = (self as unknown) as ServiceWorkerGlobalScope;
|
|
const STATIC_CACHE_NAME = `cache${version}`
|
|
const APP_CACHE_NAME = `offline${version}`;
|
|
|
|
// Hardcoded bunch of routes to always preemptively cache
|
|
const routes = ["/", "/about"];
|
|
|
|
// Hardcoded list of other assets to always preemptively cache
|
|
//const custom_assets = [
|
|
// //"https://fonts.googleapis.com/css2?family=Montserrat:wght@200&family=Roboto+Flex:opsz,wght@8..144,300;8..144,400;8..144,500&family=Roboto+Slab&display=swap"
|
|
// "https://quenten.nl/favicon.png" //Just there as a placeholder
|
|
//];
|
|
|
|
// Adds the domain to the file path, making it a full name
|
|
const addDomain = (assets: string[]) =>
|
|
assets.map((f) => self.location.origin + f);
|
|
|
|
// build is an array of all files generated by the bundler
|
|
// files is an array of all files in the static dir
|
|
const ourAssets = addDomain([
|
|
...files,
|
|
...build,
|
|
...routes
|
|
]);
|
|
|
|
const to_cache = [
|
|
...ourAssets,
|
|
// ...custom_assets
|
|
]
|
|
const staticAssets = new Set(to_cache);
|
|
|
|
worker.addEventListener("install", (event) => {
|
|
event.waitUntil(
|
|
caches
|
|
.open(STATIC_CACHE_NAME)
|
|
.then((cache) => {
|
|
to_cache.forEach((item) => {
|
|
return cache.add(item)
|
|
})
|
|
return
|
|
})
|
|
.then(() => {
|
|
worker.skipWaiting();
|
|
})
|
|
);
|
|
});
|
|
|
|
worker.addEventListener("activate", (event) => {
|
|
event.waitUntil(
|
|
caches.keys()
|
|
.then(async (keys) => {
|
|
// Delete old caches
|
|
for (const key of keys) {
|
|
if (key !== STATIC_CACHE_NAME && key !== APP_CACHE_NAME) await caches.delete(key);
|
|
}
|
|
console.log("old caches deleted")
|
|
worker.clients.claim();
|
|
})
|
|
.then(() => console.log("Activated"))
|
|
)
|
|
})
|
|
|
|
// Fetch the asset from the network and store it in the cache
|
|
// Falls back to the cache if the user is offline
|
|
async function fetchAndCache(request: Request) {
|
|
const cache = await caches.open(APP_CACHE_NAME);
|
|
|
|
try {
|
|
const response = await fetch(request);
|
|
cache.put(request, response.clone());
|
|
return response;
|
|
} catch (err) { // if the user is offline, the request will fail
|
|
const response = await cache.match(request);
|
|
if (response) return response;
|
|
|
|
// if not in cache, throw error anyway
|
|
throw err;
|
|
}
|
|
}
|
|
|
|
worker.addEventListener("fetch", (event) => {
|
|
if (event.request.method !== "GET") return;
|
|
if (new URL(event.request.url).hostname === "api.quenten.nl") return;
|
|
|
|
//console.log("fetch event intercepted")
|
|
|
|
// Range requests are unsupported for some reason
|
|
if (event.request.headers.has("range")) {
|
|
// Check if in the cache, and return if it is there,
|
|
// otherwise let the request go through and start a new request
|
|
// in the background without the range header
|
|
console.log("Request has a Range header (HTTP 206). Checking if it's in cache")
|
|
event.respondWith(
|
|
(async () => {
|
|
const url = new URL(event.request.url);
|
|
const isStaticAsset = staticAssets.has(url.href);
|
|
|
|
|
|
const cachedAsset = isStaticAsset && (await caches.match(event.request, {ignoreVary: true}));
|
|
|
|
return cachedAsset || (await fetch(event.request,))
|
|
})()
|
|
);
|
|
|
|
// Also put the thing in cache for next time!
|
|
const newRequest = new Request(event.request.url)
|
|
fetchAndCache(newRequest);
|
|
return
|
|
}
|
|
|
|
const url = new URL(event.request.url);
|
|
|
|
// Don't try to cache protocols other than http/https
|
|
const isHttp = url.protocol.startsWith("http");
|
|
const isStaticAsset = staticAssets.has(url.href);
|
|
const isDev = url.host === self.location.host;
|
|
const skipBecauseUncached = event.request.cache === 'only-if-cached' && !isStaticAsset;
|
|
|
|
if (isHttp && !skipBecauseUncached) {
|
|
event.respondWith(
|
|
(async () => {
|
|
// always serve static files and bundler-generated assets from cache.
|
|
// if your application has other URLs with data that will never change,
|
|
// set this variable to true for them, and they will only be fetched once.
|
|
const cachedAsset = isStaticAsset && (await caches.match(event.request, {ignoreVary: true}));
|
|
|
|
return cachedAsset || fetchAndCache(event.request);
|
|
})()
|
|
)
|
|
}
|
|
}) |