1// BUILD_ID is injected via importScripts from /_sw-version.js (served by 2// pages/api/sw-version.ts) as a bare lexical global (`const BUILD_ID = "..."`). 3// The browser re-fetches imported scripts during the update check (thanks to 4// updateViaCache: "none" on the registration), so changing /_sw-version.js 5// triggers install -> waiting -> activate. 6// 7// importScripts is wrapped because a synchronous throw here (e.g. /_sw-version.js 8// returning 503 during a deploy) would abort the entire SW. Falling back to a 9// placeholder keeps the SW functional; the next update check will re-import. 10// The `typeof` guard also covers a 200-with-non-declaring-body anomaly, where 11// importScripts succeeds but never declares BUILD_ID â a bare reference would 12// then ReferenceError and brick the SW. 13let resolvedBuildId = "unknown"; 14try { 15 importScripts("/_sw-version.js"); 16 if (typeof BUILD_ID !== "undefined") resolvedBuildId = BUILD_ID; 17} catch (e) { 18 // Keep the "unknown" fallback; the next update check re-imports. 19} 20 21const CACHE_NAME = `hidden-static-${resolvedBuildId}`; 22 23self.addEventListener("install", (event) => { 24 // No skipWaiting here â the client decides when to promote via the 25 // SKIP_WAITING message. That keeps a single path for activation and 26 // allows the existing controller to remain in charge until the client 27 // is ready to switch over. 28}); 29 30self.addEventListener("activate", (event) => { 31 event.waitUntil( 32 caches.keys() 33 .then(names => Promise.all( 34 names 35 .filter(n => n.startsWith("hidden-static-") && n !== CACHE_NAME) 36 .map(n => caches.delete(n)) 37 )) 38 .then(() => self.clients.claim()) 39 ); 40}); 41 42self.addEventListener("fetch", (event) => { 43 const { request } = event; 44 45 if (request.method !== "GET") return; 46 47 if (request.mode === "navigate") { 48 event.respondWith( 49 fetch(request).catch(() => caches.match(request)) 50 ); 51 return; 52 } 53 54 if (request.url.includes("/_next/static/")) { 55 event.respondWith( 56 caches.match(request).then(cached => { 57 if (cached) return cached; 58 return fetch(request).then(response => { 59 if (response.ok) { 60 const clone = response.clone(); 61 caches.open(CACHE_NAME).then(cache => cache.put(request, clone)); 62 } 63 return response; 64 }); 65 }) 66 ); 67 return; 68 } 69}); 70 71self.addEventListener("message", (event) => { 72 if (event.data?.type === "SKIP_WAITING") { 73 self.skipWaiting(); 74 } 75});
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.