1const CACHE_NAME = 'careerdiary-shell-v3'; 2 3self.addEventListener('install', () => { 4 // Activate immediately â don't wait for existing clients to close 5 self.skipWaiting(); 6}); 7 8self.addEventListener('activate', (event) => { 9 // Clean up ALL old caches 10 event.waitUntil( 11 caches.keys().then((keys) => 12 Promise.all(keys.filter((key) => key !== CACHE_NAME).map((key) => caches.delete(key))) 13 ).then(() => self.clients.claim()) 14 ); 15}); 16 17self.addEventListener('fetch', (event) => { 18 if (event.request.method !== 'GET') return; 19 20 const url = new URL(event.request.url); 21 22 // Skip caching for API calls and Supabase requests 23 if (url.pathname.startsWith('/api/') || url.hostname.includes('supabase')) { 24 return; 25 } 26 27 // Navigation requests (HTML pages) â always go to network first 28 if (event.request.mode === 'navigate') { 29 event.respondWith( 30 fetch(event.request).catch(() => 31 caches.match(event.request) 32 .then((cached) => cached || caches.match('/index.html')) 33 .then((fallback) => fallback || new Response('Offline', { status: 503, headers: { 'Content-Type': 'text/html' } })) 34 ) 35 ); 36 return; 37 } 38 39 // Hashed assets (Vite fingerprinted files) â cache-first is safe because 40 // content changes produce new filenames automatically 41 const isHashedAsset = /\/assets\/[^/]+\.[a-f0-9]{8,}\.\w+$/.test(url.pathname); 42 if (isHashedAsset) { 43 event.respondWith( 44 caches.match(event.request).then((cached) => { 45 if (cached) return cached; 46 return fetch(event.request).then((response) => { 47 const clone = response.clone(); 48 caches.open(CACHE_NAME).then((cache) => cache.put(event.request, clone)); 49 return response; 50 }); 51 }) 52 ); 53 return; 54 } 55 56 // Everything else (manifest, favicon, etc.) â network-first with cache fallback 57 event.respondWith( 58 fetch(event.request) 59 .then((response) => { 60 const clone = response.clone(); 61 caches.open(CACHE_NAME).then((cache) => cache.put(event.request, clone)); 62 return response; 63 }) 64 .catch(() => caches.match(event.request).then((cached) => cached || new Response('', { status: 503 }))) 65 ); 66});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.