1// Spreka AI â Service Worker 2const CACHE_VERSION = 'spreka-v3'; 3const OFFLINE_URL = '/offline.html'; 4 5// Assets to pre-cache on install 6const PRECACHE_ASSETS = [ 7 OFFLINE_URL, 8 '/favicon.ico', 9 '/favicon-96x96.png', 10 '/apple-touch-icon.png', 11 '/pwa-icon-192.png', 12 '/pwa-icon-512.png', 13]; 14 15// Install: pre-cache offline page + core assets 16self.addEventListener('install', (event) => { 17 event.waitUntil( 18 caches.open(CACHE_VERSION).then((cache) => { 19 return cache.addAll(PRECACHE_ASSETS); 20 }) 21 ); 22 // Activate new SW immediately 23 self.skipWaiting(); 24}); 25 26// Activate: clean up old caches 27self.addEventListener('activate', (event) => { 28 event.waitUntil( 29 caches.keys().then((cacheNames) => { 30 return Promise.all( 31 cacheNames 32 .filter((name) => name !== CACHE_VERSION) 33 .map((name) => caches.delete(name)) 34 ); 35 }) 36 ); 37 // Take control of all clients immediately 38 self.clients.claim(); 39}); 40 41// Fetch: Network-first for navigation, Cache-first for static assets 42self.addEventListener('fetch', (event) => { 43 const { request } = event; 44 45 // Only handle GET requests 46 if (request.method !== 'GET') return; 47 48 // Skip cross-origin requests 49 if (!request.url.startsWith(self.location.origin)) return; 50 51 // Skip Livewire/API requests 52 if (request.url.includes('/livewire/') || request.url.includes('/api/')) return; 53 54 // Navigation requests (HTML pages): Network-first with offline fallback 55 if (request.mode === 'navigate') { 56 event.respondWith( 57 fetch(request) 58 .then((response) => { 59 // Cache successful navigation responses 60 if (response.ok) { 61 const responseClone = response.clone(); 62 caches.open(CACHE_VERSION).then((cache) => { 63 cache.put(request, responseClone); 64 }); 65 } 66 return response; 67 }) 68 .catch(() => { 69 // Try cache first, then offline page 70 return caches.match(request).then((cached) => { 71 return cached || caches.match(OFFLINE_URL); 72 }); 73 }) 74 ); 75 return; 76 } 77 78 // Static assets (CSS, JS, images, fonts): Cache-first with network fallback 79 if ( 80 request.destination === 'style' || 81 request.destination === 'script' || 82 request.destination === 'image' || 83 request.destination === 'font' || 84 request.url.includes('/build/') 85 ) { 86 event.respondWith( 87 caches.match(request).then((cached) => { 88 if (cached) return cached; 89 90 return fetch(request).then((response) => { 91 if (response.ok) { 92 const responseClone = response.clone(); 93 caches.open(CACHE_VERSION).then((cache) => { 94 cache.put(request, responseClone); 95 }); 96 } 97 return response; 98 }); 99 }) 100 ); 101 return; 102 } 103});
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.