1const CACHE_NAME = "ai-pals-v3"; 2const OFFLINE_URL = "/offline"; 3 4const PRECACHE_ASSETS = ["/offline", "/manifest.json", "/icons/icon-192.png", "/icons/icon-512.png"]; 5 6self.addEventListener("install", (event) => { 7 event.waitUntil( 8 caches.open(CACHE_NAME).then((cache) => cache.addAll(PRECACHE_ASSETS)) 9 ); 10 self.skipWaiting(); 11}); 12 13self.addEventListener("activate", (event) => { 14 event.waitUntil( 15 caches.keys().then((keys) => 16 Promise.all(keys.filter((key) => key !== CACHE_NAME).map((key) => caches.delete(key))) 17 ) 18 ); 19 self.clients.claim(); 20}); 21 22self.addEventListener("fetch", (event) => { 23 const { request } = event; 24 25 if (request.method !== "GET") return; 26 27 // Navigation requests: network-first, fallback to offline page 28 if (request.mode === "navigate") { 29 event.respondWith( 30 fetch(request) 31 .then((response) => { 32 const clone = response.clone(); 33 caches.open(CACHE_NAME).then((cache) => cache.put(request, clone)); 34 return response; 35 }) 36 .catch(() => caches.match(OFFLINE_URL).then((r) => r || caches.match("/"))) 37 ); 38 return; 39 } 40 41 // Never cache Next.js dev/build chunks â they change on every recompile 42 if (request.url.includes("/_next/")) { 43 return; 44 } 45 46 // Static assets: cache-first (only for non-Next.js assets like icons, fonts from public/) 47 if ( 48 request.destination === "script" || 49 request.destination === "style" || 50 request.destination === "image" || 51 request.destination === "font" 52 ) { 53 event.respondWith( 54 caches.match(request).then( 55 (cached) => 56 cached || 57 fetch(request).then((response) => { 58 const clone = response.clone(); 59 caches.open(CACHE_NAME).then((cache) => cache.put(request, clone)); 60 return response; 61 }) 62 ) 63 ); 64 return; 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.