Files
Ustagammon/web/sw.js

73 lines
2.6 KiB
JavaScript

// sw.js -- service worker d'Ustagammon : l'application hors ligne.
//
// Copyright (C) 2026 les auteurs d'Ustagammon.
// Licence : GPLv3 ou ultérieure (voir LICENSE).
//
// À l'installation, tous les fichiers du site (dont les 8,7 Mo de données du
// moteur) sont mis en cache ; ensuite, chaque fichier est servi depuis ce
// cache, sans réseau. VERSION et FILES sont écrits en tête de ce fichier par
// scripts/service-worker.sh au moment de make site.
//
// Mise à jour : à chaque publication, VERSION change, donc ce fichier. Le
// navigateur installe alors la nouvelle version, qui télécharge tout dans un
// nouveau cache, puis attend : la version en place garde la main, et son
// cache, tant que le joueur n'a pas accepté la mise à jour. Une page ouverte
// continue donc de trouver tous ses fichiers. L'application affiche le
// bandeau « Nouvelle version disponible » (app/src/ui/updates.ts) ; « Mettre
// à jour » envoie le message « skip-waiting » : la nouvelle version prend
// la main, efface l'ancien cache, et la page se recharge. À la toute
// première installation, aucune version n'est en place : elle prend la main
// sans attendre.
/* global VERSION, FILES */
const CACHE = `ustagammon-${VERSION}`;
self.addEventListener("install", (event) => {
event.waitUntil(
(async () => {
const cache = await caches.open(CACHE);
// no-cache : revalider auprès du serveur, jamais une copie
// périmée du cache HTTP du navigateur.
await cache.addAll(FILES.map((file) => new Request(file, { cache: "no-cache" })));
})(),
);
});
// L'accord du joueur (même nom que SKIP_WAITING dans updates.ts).
self.addEventListener("message", (event) => {
if (event.data?.type === "skip-waiting") {
void self.skipWaiting();
}
});
self.addEventListener("activate", (event) => {
event.waitUntil(
(async () => {
for (const name of await caches.keys()) {
if (name !== CACHE) {
await caches.delete(name);
}
}
await self.clients.claim();
})(),
);
});
self.addEventListener("fetch", (event) => {
const request = event.request;
if (request.method !== "GET" || new URL(request.url).origin !== self.location.origin) {
return;
}
event.respondWith(
(async () => {
const cached = await caches.match(request, {
cacheName: CACHE,
ignoreSearch: true,
ignoreVary: true,
});
return cached ?? fetch(request);
})(),
);
});