Skip to content

Instantly share code, notes, and snippets.

@Mlocik97
Last active November 16, 2023 10:53
Show Gist options
  • Save Mlocik97/cf0f4c39e46d45404fda8808a25244c8 to your computer and use it in GitHub Desktop.
Save Mlocik97/cf0f4c39e46d45404fda8808a25244c8 to your computer and use it in GitHub Desktop.
import { build, files, version } from '$service-worker';
// https://github.com/microsoft/TypeScript/issues/11781 - this is needed for TS and ESLint
/// env serviceworker
const globalThis = /** @type {unknown} */ (self);
/// <reference no-default-lib="true"/>
/// <reference lib="es2020" />
/// <reference lib="WebWorker" />
const sw = /** @type {ServiceWorkerGlobalScope & typeof globalThis} */ (globalThis);
const ASSETS = `cache${version}`;
// `build` is an array of all the files generated by the bundler,
// `files` is an array of everything in the `static` directory
const to_cache = build.concat(files);
const staticAssets = new Set(to_cache);
/** @param {ExtendableEvent} event */
function install_listener(event) {
event.waitUntil(
caches
.open(ASSETS)
.then((cache) => cache.addAll(to_cache))
.then(() => {
sw.skipWaiting();
})
);
}
/** @param {ExtendableEvent} event */
function activate_listener(event) {
event.waitUntil(
caches.keys().then(async (keys) => {
// delete old caches
for (const key of keys) {
if (key !== ASSETS)
await caches.delete(key);
}
sw.clients.claim();
})
);
}
/**
* Fetch the asset from the network and store it in the cache.
* Fall back to the cache if the user is offline.
* @param {RequestInfo} request
*/
async function fetchAndCache(request) {
const cache = await caches.open(`offline${version}`);
try {
const response = await fetch(request);
cache.put(request, response.clone());
return response;
} catch (err) {
const response = await cache.match(request);
if (response) return response;
throw err;
}
}
/** @param {FetchEvent} event */
function fetch_listener(event) {
if (event.request.method !== 'GET' || event.request.headers.has('range'))
return;
const url = new URL(event.request.url);
// don't try to handle e.g. data: URIs
const isHttp = url.protocol.startsWith('http');
const isDevServerRequest = url.hostname === sw.location.hostname && url.port !== sw.location.port;
const isStaticAsset = url.host === sw.location.host && staticAssets.has(url.pathname);
const skipBecauseUncached = event.request.cache === 'only-if-cached' && !isStaticAsset;
if (isHttp && !isDevServerRequest && !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));
// for pages, you might want to serve a build `service-worker-index.html` file.
// It's not right for every app, but if it's right for yours then uncomment this section
/*
if (!cachedAsset && url.origin === sw.origin && routes.find(route => route.pattern.test(url.pathname))) {
return caches.match('/service-worker-index.html');
}
*/
return cachedAsset || fetchAndCache(event.request);
})()
);
}
}
// prettier-ignore
sw.addEventListener('install' , install_listener);
// prettier-ignore
sw.addEventListener('activate', activate_listener);
// prettier-ignore
sw.addEventListener('fetch' , fetch_listener);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment