const CACHE_NAME = "nowhatever-v1"; const PRECACHE_URLS = ["/", "/offline"]; self.addEventListener("install", (event) => { event.waitUntil( caches .open(CACHE_NAME) .then((cache) => cache.addAll(PRECACHE_URLS)) .then(() => self.skipWaiting()) ); }); self.addEventListener("activate", (event) => { event.waitUntil( caches .keys() .then((keys) => Promise.all( keys .filter((key) => key !== CACHE_NAME) .map((key) => caches.delete(key)) ) ) .then(() => self.clients.claim()) ); }); self.addEventListener("fetch", (event) => { const { request } = event; if (request.method !== "GET") return; const url = new URL(request.url); // API calls: network-only if (url.pathname.startsWith("/api/")) return; // Static assets (_next/static, icons, fonts): cache-first if ( url.pathname.startsWith("/_next/static/") || url.pathname.match(/\.(png|jpg|svg|ico|woff2?)$/) ) { event.respondWith( caches.match(request).then( (cached) => cached || fetch(request).then((response) => { const clone = response.clone(); caches.open(CACHE_NAME).then((cache) => cache.put(request, clone)); return response; }) ) ); return; } // HTML pages: network-first, fallback to cache, then offline page event.respondWith( fetch(request) .then((response) => { const clone = response.clone(); caches.open(CACHE_NAME).then((cache) => cache.put(request, clone)); return response; }) .catch(() => caches.match(request).then((cached) => cached || caches.match("/offline"))) ); });