const CACHE_NAME = 'mockupaws-v1'; const STATIC_ASSETS = [ '/', '/index.html', '/manifest.json', '/favicon.ico', ]; // Install event - cache static assets self.addEventListener('install', (event) => { event.waitUntil( caches.open(CACHE_NAME).then((cache) => { return cache.addAll(STATIC_ASSETS); }) ); // Skip waiting to activate immediately self.skipWaiting(); }); // Activate event - clean up old caches self.addEventListener('activate', (event) => { event.waitUntil( caches.keys().then((cacheNames) => { return Promise.all( cacheNames .filter((name) => name !== CACHE_NAME) .map((name) => caches.delete(name)) ); }) ); // Claim clients immediately self.clients.claim(); }); // Fetch event - stale-while-revalidate strategy self.addEventListener('fetch', (event) => { const { request } = event; // Skip non-GET requests if (request.method !== 'GET') { return; } // Skip API requests if (request.url.includes('/api/') || request.url.includes('localhost:8000')) { return; } // Stale-while-revalidate for static assets event.respondWith( caches.match(request).then((cachedResponse) => { // Return cached response immediately (stale) const fetchPromise = fetch(request) .then((networkResponse) => { // Update cache in background (revalidate) if (networkResponse.ok) { const clone = networkResponse.clone(); caches.open(CACHE_NAME).then((cache) => { cache.put(request, clone); }); } return networkResponse; }) .catch(() => { // Network failed, already returned cached response }); return cachedResponse || fetchPromise; }) ); });