// Service Worker — Illustrations DB const VERSION = 'v1.0.2'; const STATIC_CACHE = `static-${VERSION}`; const PAGES_CACHE = `pages-${VERSION}`; const OFFLINE_URL = '/offline/'; const STATIC_ASSETS = [ '/', // optional: remove if you don’t want to cache / '/static/pwa/icon-192.png', '/static/pwa/icon-512.png' ]; self.addEventListener('install', (event) => { event.waitUntil( caches.open(STATIC_CACHE).then((cache) => cache.addAll(STATIC_ASSETS)) .then(() => self.skipWaiting()) ); }); self.addEventListener('activate', (event) => { event.waitUntil( caches.keys().then((keys) => Promise.all( keys.filter(k => ![STATIC_CACHE, PAGES_CACHE].includes(k)) .map(k => caches.delete(k)) ) ).then(() => self.clients.claim()) ); }); function isNavigation(req) { return req.mode === 'navigate' || (req.method === 'GET' && req.headers.get('accept')?.includes('text/html')); } self.addEventListener('fetch', (event) => { const req = event.request; if (req.method !== 'GET') return; // HTML pages: stale-while-revalidate w/ offline fallback if (isNavigation(req)) { event.respondWith((async () => { try { const network = await fetch(req); const cache = await caches.open(PAGES_CACHE); cache.put(req, network.clone()); return network; } catch { const cache = await caches.open(PAGES_CACHE); const cached = await cache.match(req); return cached || caches.match(OFFLINE_URL); } })()); return; } // Static files under /static: cache-first const url = new URL(req.url); if (url.pathname.startsWith('/static/')) { event.respondWith((async () => { const cache = await caches.open(STATIC_CACHE); const cached = await cache.match(req); if (cached) return cached; try { const network = await fetch(req); cache.put(req, network.clone()); return network; } catch { return cached; // best effort } })()); return; } // Default: pass-through });