62 lines
2.6 KiB
JavaScript
62 lines
2.6 KiB
JavaScript
/* The build replaces both tokens; this file is never registered in development. */
|
|
const VERSION = __CACHE_VERSION__;
|
|
const FILES = __PRECACHE_FILES__;
|
|
const PREFIX = `rhine-lab:${new URL(self.registration.scope).pathname}:`;
|
|
const CACHE = PREFIX + VERSION;
|
|
const urls = FILES.map(path => new URL(path, self.registration.scope).href);
|
|
const allowed = new Set(urls);
|
|
const index = new URL("index.html", self.registration.scope).href;
|
|
|
|
self.addEventListener("install", event => {
|
|
event.waitUntil((async () => {
|
|
try {
|
|
const cache = await caches.open(CACHE);
|
|
// Limit connections so a complete font family does not flood the page.
|
|
// Keep successful files private until every resource is present; failure
|
|
// still deletes this entire release and leaves the active release intact.
|
|
let next = 0;
|
|
const workers = Array.from({ length: 6 }, async () => {
|
|
while (next < urls.length) {
|
|
const url = urls[next++];
|
|
const immutable = /\/fonts\/misans-webfont-4\.3\.1\//.test(url) || /\/assets\/archive-(cassette|assembly)\.[a-f0-9]{16}\.glb$/.test(url);
|
|
await cache.add(new Request(url, { cache: immutable ? "default" : "no-cache" }));
|
|
}
|
|
});
|
|
const results = await Promise.allSettled(workers);
|
|
const failure = results.find(result => result.status === "rejected");
|
|
if (failure) throw failure.reason;
|
|
} catch (error) {
|
|
await caches.delete(CACHE);
|
|
throw error;
|
|
}
|
|
})());
|
|
});
|
|
self.addEventListener("activate", event => {
|
|
event.waitUntil((async () => {
|
|
for (const key of await caches.keys())
|
|
if (key.startsWith(PREFIX) && key !== CACHE) await caches.delete(key);
|
|
await self.clients.claim();
|
|
})());
|
|
});
|
|
self.addEventListener("message", event => {
|
|
if (event.data?.type === "RHINE_APPLY_UPDATE") event.waitUntil(self.skipWaiting());
|
|
});
|
|
self.addEventListener("fetch", event => {
|
|
if (event.request.method !== "GET") return;
|
|
const url = new URL(event.request.url);
|
|
if (url.origin !== self.location.origin) return;
|
|
url.search = "";
|
|
url.hash = "";
|
|
const navigation = event.request.mode === "navigate" &&
|
|
(url.href === self.registration.scope || url.href === index);
|
|
const key = navigation ? index : url.href;
|
|
if (!allowed.has(key)) return;
|
|
event.respondWith((async () => {
|
|
const cache = await caches.open(CACHE);
|
|
// HTML, hashed bundles and stable model URLs come from the same release.
|
|
// A new release stays waiting until the user chooses to restart or exits.
|
|
const cached = await cache.match(key);
|
|
return cached ?? fetch(event.request);
|
|
})());
|
|
});
|