Service worker: network-first for the app shell

Cache-first meant players kept loading the previous build until their
second visit - a redeploy was invisible. The shell is now fetched from
the network first and falls back to the cache when offline; the icons and
manifest stay cache-first. Cache name bumped to v2 to drop old copies.
This commit is contained in:
Dave 2026-10-23 20:10:09 +02:00
parent 15b37e7cc9
commit 43db37e63b

36
sw.js
View file

@ -1,7 +1,10 @@
/* Mineflappy offline cache.
Cache-first for the app shell, with a background refresh so a new
deploy is picked up on the next visit. */
const CACHE = 'mineflappy-v1';
The app shell (index.html) is fetched NETWORK-FIRST so a new deploy
reaches the player immediately; if the network is down it falls back to
the cached copy. The icons and manifest are cache-first because they
only change with a version bump. */
const CACHE = 'mineflappy-v2';
const ASSETS = [
'./',
'./index.html',
@ -28,10 +31,33 @@ self.addEventListener('activate', e => {
);
});
function isAppShell(url) {
return url.pathname.endsWith('/') ||
url.pathname.endsWith('/index.html') ||
url.pathname.endsWith('/sw.js');
}
self.addEventListener('fetch', e => {
const req = e.request;
if (req.method !== 'GET' || new URL(req.url).origin !== location.origin) return;
if (req.method !== 'GET') return;
const url = new URL(req.url);
if (url.origin !== location.origin) return;
if (isAppShell(url)) {
/* network first - a redeploy shows up straight away */
e.respondWith(
fetch(req).then(res => {
if (res && res.status === 200) {
const copy = res.clone();
caches.open(CACHE).then(c => c.put(req, copy));
}
return res;
}).catch(() => caches.match(req).then(hit => hit || caches.match('./index.html')))
);
return;
}
/* everything else: cache first, refresh in the background */
e.respondWith(
caches.match(req).then(hit => {
const network = fetch(req).then(res => {
@ -40,7 +66,7 @@ self.addEventListener('fetch', e => {
caches.open(CACHE).then(c => c.put(req, copy));
}
return res;
}).catch(() => hit || caches.match('./index.html'));
}).catch(() => hit);
return hit || network;
})
);