fix: bump SW version and switch to network-first caching
VERSION was stuck at raycer-v1 so mobile PWAs never picked up the streak fix (cache-first served the stale stats.js forever). - Bump to raycer-v2 → triggers install, purges old caches - Switch same-origin assets from cache-first to network-first so future deploys propagate immediately; cache is only used as an offline fallback - Simplify to a single SHELL_CACHE (no separate runtime cache) - Cross-origin vendor assets (Dexie CDN) stay cache-first
This commit is contained in:
parent
392bd6416e
commit
e410f09c93
1 changed files with 19 additions and 35 deletions
|
|
@ -1,14 +1,13 @@
|
||||||
/* raycer service worker
|
/* raycer service worker
|
||||||
* - app shell: cache-first
|
* - app shell: network-first (so deploys propagate immediately), cache fallback for offline
|
||||||
* - /api/*: network-first with no cache fallback (data lives in Dexie)
|
* - /api/*: network-only (data lives in Dexie)
|
||||||
* - dexie CDN module: cache-first (so the app boots offline)
|
* - cross-origin (Dexie CDN): cache-first (immutable vendor assets)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const VERSION = 'raycer-v1';
|
const VERSION = 'raycer-v2';
|
||||||
const SHELL_CACHE = `${VERSION}-shell`;
|
const SHELL_CACHE = `${VERSION}-shell`;
|
||||||
const RUNTIME_CACHE = `${VERSION}-runtime`;
|
|
||||||
|
|
||||||
const SHELL = [
|
const PRECACHE = [
|
||||||
'/',
|
'/',
|
||||||
'/index.html',
|
'/index.html',
|
||||||
'/manifest.webmanifest',
|
'/manifest.webmanifest',
|
||||||
|
|
@ -28,7 +27,7 @@ self.addEventListener('install', (event) => {
|
||||||
event.waitUntil(
|
event.waitUntil(
|
||||||
(async () => {
|
(async () => {
|
||||||
const cache = await caches.open(SHELL_CACHE);
|
const cache = await caches.open(SHELL_CACHE);
|
||||||
await cache.addAll(SHELL);
|
await cache.addAll(PRECACHE);
|
||||||
self.skipWaiting();
|
self.skipWaiting();
|
||||||
})()
|
})()
|
||||||
);
|
);
|
||||||
|
|
@ -40,7 +39,7 @@ self.addEventListener('activate', (event) => {
|
||||||
const keys = await caches.keys();
|
const keys = await caches.keys();
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
keys
|
keys
|
||||||
.filter((k) => !k.startsWith(VERSION))
|
.filter((k) => k !== SHELL_CACHE)
|
||||||
.map((k) => caches.delete(k))
|
.map((k) => caches.delete(k))
|
||||||
);
|
);
|
||||||
await self.clients.claim();
|
await self.clients.claim();
|
||||||
|
|
@ -54,7 +53,7 @@ self.addEventListener('fetch', (event) => {
|
||||||
|
|
||||||
const url = new URL(req.url);
|
const url = new URL(req.url);
|
||||||
|
|
||||||
// API: network-first, never cache
|
// API: network-only, never cache
|
||||||
if (url.pathname.startsWith('/api/')) {
|
if (url.pathname.startsWith('/api/')) {
|
||||||
event.respondWith(
|
event.respondWith(
|
||||||
fetch(req).catch(
|
fetch(req).catch(
|
||||||
|
|
@ -67,39 +66,24 @@ self.addEventListener('fetch', (event) => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Same-origin SPA navigations: serve cached shell, fall back to network
|
// Same-origin (app shell + assets): network-first, cache fallback for offline
|
||||||
if (req.mode === 'navigate') {
|
|
||||||
event.respondWith(
|
|
||||||
(async () => {
|
|
||||||
try {
|
|
||||||
const fresh = await fetch(req);
|
|
||||||
const cache = await caches.open(SHELL_CACHE);
|
|
||||||
cache.put('/index.html', fresh.clone()).catch(() => {});
|
|
||||||
return fresh;
|
|
||||||
} catch {
|
|
||||||
const cached = await caches.match('/index.html');
|
|
||||||
if (cached) return cached;
|
|
||||||
return new Response('offline', { status: 503 });
|
|
||||||
}
|
|
||||||
})()
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Same-origin assets: cache-first
|
|
||||||
if (url.origin === self.location.origin) {
|
if (url.origin === self.location.origin) {
|
||||||
event.respondWith(
|
event.respondWith(
|
||||||
(async () => {
|
(async () => {
|
||||||
const cached = await caches.match(req);
|
|
||||||
if (cached) return cached;
|
|
||||||
try {
|
try {
|
||||||
const fresh = await fetch(req);
|
const fresh = await fetch(req);
|
||||||
if (fresh.ok) {
|
if (fresh.ok) {
|
||||||
const cache = await caches.open(RUNTIME_CACHE);
|
const cache = await caches.open(SHELL_CACHE);
|
||||||
cache.put(req, fresh.clone()).catch(() => {});
|
cache.put(req, fresh.clone()).catch(() => {});
|
||||||
}
|
}
|
||||||
return fresh;
|
return fresh;
|
||||||
} catch {
|
} catch {
|
||||||
|
const cached = await caches.match(req);
|
||||||
|
if (cached) return cached;
|
||||||
|
if (req.mode === 'navigate') {
|
||||||
|
const shell = await caches.match('/index.html');
|
||||||
|
if (shell) return shell;
|
||||||
|
}
|
||||||
return new Response('offline', { status: 503 });
|
return new Response('offline', { status: 503 });
|
||||||
}
|
}
|
||||||
})()
|
})()
|
||||||
|
|
@ -107,7 +91,7 @@ self.addEventListener('fetch', (event) => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cross-origin (e.g. Dexie CDN): cache-first
|
// Cross-origin (e.g. Dexie CDN): cache-first (immutable vendor assets)
|
||||||
event.respondWith(
|
event.respondWith(
|
||||||
(async () => {
|
(async () => {
|
||||||
const cached = await caches.match(req);
|
const cached = await caches.match(req);
|
||||||
|
|
@ -115,12 +99,12 @@ self.addEventListener('fetch', (event) => {
|
||||||
try {
|
try {
|
||||||
const fresh = await fetch(req);
|
const fresh = await fetch(req);
|
||||||
if (fresh.ok) {
|
if (fresh.ok) {
|
||||||
const cache = await caches.open(RUNTIME_CACHE);
|
const cache = await caches.open(SHELL_CACHE);
|
||||||
cache.put(req, fresh.clone()).catch(() => {});
|
cache.put(req, fresh.clone()).catch(() => {});
|
||||||
}
|
}
|
||||||
return fresh;
|
return fresh;
|
||||||
} catch {
|
} catch {
|
||||||
return cached || new Response('offline', { status: 503 });
|
return new Response('offline', { status: 503 });
|
||||||
}
|
}
|
||||||
})()
|
})()
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue