// PWA Service Worker v2 // - 页面导航:网络优先(构建更新后强制拿到新 index.html),离线才回落缓存 // - 静态资源:缓存优先 // - /api:直连不缓存 const CACHE = 'fp-static-v2'; const CORE = ['/', '/manifest.webmanifest', '/icons/pwa-192.png', '/icons/pwa-512.png']; self.addEventListener('install', (e) => { self.skipWaiting(); e.waitUntil(caches.open(CACHE).then((c) => c.addAll(CORE))); }); self.addEventListener('activate', (e) => { e.waitUntil( caches.keys() .then((ks) => Promise.all(ks.filter((k) => k !== CACHE).map((k) => caches.delete(k)))) .then(() => self.clients.claim()) ); }); self.addEventListener('fetch', (e) => { const url = new URL(e.request.url); if (e.request.method !== 'GET' || url.pathname.startsWith('/api')) return; if (e.request.mode === 'navigate') { e.respondWith( fetch(e.request).then((res) => { const copy = res.clone(); caches.open(CACHE).then((c) => c.put('/index.html', copy)); return res; }).catch(() => caches.match('/index.html').then((h) => h || caches.match('/'))) ); return; } e.respondWith( caches.match(e.request).then((hit) => hit || fetch(e.request).then((res) => { if (res.ok && url.origin === location.origin) { const copy = res.clone(); caches.open(CACHE).then((c) => c.put(e.request, copy)); } return res; })) ); });