UNPKG

aliaset

Version:
150 lines (119 loc) 3.96 kB
/* eslint-env serviceworker */ /// env serviceworker /// <reference no-default-lib="true"/> /// <reference lib="es2020" /> /// <reference lib="WebWorker" /> const sw = self as unknown as ServiceWorkerGlobalScope & typeof globalThis import { build as immutables, files as staticFiles, version } from '$service-worker' const CACHE_PREFIX = 'app-cache-' const cacheName = `${CACHE_PREFIX}${version}` const cachePromise = caches.open(cacheName) // Precaching // - immutables // Runtime caching // - /_app/version.json: network first - to detect new versions // - static: stale while revalidate - cache first and update cache from network // - *: cache first const NETWORK_FIRST = new Set(['/' + __SVELTEKIT_APP_VERSION_FILE__]) const STALE_WHILE_REVALIDATE = new Set(staticFiles) sw.addEventListener('install', (event) => { event.waitUntil( cachePromise.then((cache) => // re-use from existing cache for hashed files Promise.all( immutables.map((file) => caches.match(file).then((response) => { if (response) { return cache.put(file, response) } return cache.add(file) }), ), ), ), ) }) // Activate the worker after notification from client sw.addEventListener('message', (event) => { if (event.data?.type === 'activate') { sw.skipWaiting() } }) // On version update, remove old cached files sw.addEventListener('activate', (event) => { // event.waitUntil( // (async function () { // // Feature-detect // if (sw.registration.navigationPreload) { // // Enable navigation preloads! // await sw.registration.navigationPreload.enable() // } // })(), // ) sw.caches .keys() .then((keys) => Promise.all( keys .filter((key) => key.startsWith(CACHE_PREFIX) && key !== cacheName) .map((key) => caches.delete(key)), ), ) .catch((error) => console.warn('Failed to cleanup old caches', error)) }) // Cache falling back to network strategy sw.addEventListener('fetch', (event) => { let { request } = event if (request.method !== 'GET' || request.headers.has('range')) return const url = new URL(request.url) // only cache our resources if (url.origin === location.origin) { if (url.pathname === '/-/search') { // include x-app-version to create immutable response which can be cached request = new Request(request, { headers: { 'x-app-version': version } }) } const strategy = NETWORK_FIRST.has(url.pathname) ? networkFirst : STALE_WHILE_REVALIDATE.has(url.pathname) ? staleWhileRevalidate : cacheFirst event.respondWith(strategy(request)) } }) function networkFirst(request: Request) { return load(request).catch(async (error) => { // If the network is unavailable // Respond from the cache if we can const cached = await fromCache(request) if (cached) return cached throw error }) } async function cacheFirst(request: Request) { const cached = await fromCache(request) if (cached) return cached return load(request) } async function staleWhileRevalidate(request: Request) { const cached = await fromCache(request) // update cache from network const revalidated = load(request) // prioritize cached response over network return cached || revalidated } async function fromCache(request: Request) { // If the network is unavailable, get // Respond from the cache if we can const cached = await caches.match(request) if (cached) return cached // // Else, use the preloaded response, if it's there // const preloaded = await event.preloadResponse // if (preloaded) return preloaded } async function load(request: Request) { const response = await fetch(request) if (response.ok && response.type === 'basic') { await (await cachePromise).put(request, response.clone()) } return response }