46 lines
1.7 KiB
JavaScript
46 lines
1.7 KiB
JavaScript
// EffectCraft service worker: the app works offline once loaded, and installs as an app.
|
|
//
|
|
// `cargo xtask web` fills in the build's file list and version. Every file is precached into a
|
|
// cache named after the version, served cache-first (responses keep the server's headers, so
|
|
// the page stays cross-origin isolated: COOP/COEP), and old versions are dropped once the new
|
|
// one activates. Anything else same-origin is fetched from the network and cached for next time.
|
|
const VERSION = "__EC_VERSION__";
|
|
const FILES = __EC_FILES__;
|
|
const CACHE = `effectcraft-${VERSION}`;
|
|
|
|
self.addEventListener("install", (event) => {
|
|
event.waitUntil(
|
|
caches
|
|
.open(CACHE)
|
|
.then((c) => c.addAll(FILES.map((f) => new Request(f, { cache: "reload" }))))
|
|
.then(() => self.skipWaiting()),
|
|
);
|
|
});
|
|
|
|
self.addEventListener("activate", (event) => {
|
|
event.waitUntil(
|
|
caches
|
|
.keys()
|
|
.then((keys) => Promise.all(keys.filter((k) => k.startsWith("effectcraft-") && k !== CACHE).map((k) => caches.delete(k))))
|
|
.then(() => self.clients.claim()),
|
|
);
|
|
});
|
|
|
|
self.addEventListener("fetch", (event) => {
|
|
const req = event.request;
|
|
const url = new URL(req.url);
|
|
if (req.method !== "GET" || url.origin !== self.location.origin) return;
|
|
event.respondWith(
|
|
(async () => {
|
|
const cache = await caches.open(CACHE);
|
|
// The page itself regardless of its query (?empty, ?demo…).
|
|
const key = req.mode === "navigate" ? new URL("./", self.registration.scope).href : req;
|
|
const hit = await cache.match(key, { ignoreSearch: req.mode === "navigate" });
|
|
if (hit) return hit;
|
|
const res = await fetch(req);
|
|
if (res.ok && res.type === "basic") cache.put(req, res.clone());
|
|
return res;
|
|
})(),
|
|
);
|
|
});
|