// Service Worker – stellt sicher dass nach einem Deploy immer der neue Stand geladen wird // index.html und API: immer vom Netzwerk (no-store) // Assets (JS/CSS mit Hash): Network-first mit Cache-Fallback für Offline const CACHE_NAME = 'dickendock-v2'; self.addEventListener('install', () => { self.skipWaiting(); // sofort aktivieren ohne auf Tab-Schließen zu warten }); self.addEventListener('activate', e => { e.waitUntil( caches.keys() .then(keys => Promise.all(keys.map(k => caches.delete(k)))) .then(() => self.clients.claim()) // alle offenen Tabs sofort übernehmen ); }); self.addEventListener('fetch', e => { const url = new URL(e.request.url); // API-Requests: nie cachen if (url.pathname.startsWith('/api/')) { e.respondWith(fetch(e.request)); return; } // HTML-Navigation (index.html, /, /*, alle Routen): immer frisch vom Server // Das ist der Kern: verhindert dass eine alte index.html aus dem HTTP-Cache kommt if (e.request.mode === 'navigate') { e.respondWith( fetch(e.request, { cache: 'no-store', // Browser-HTTP-Cache umgehen headers: { 'Cache-Control': 'no-cache' } }).catch(() => caches.match('/index.html')) // nur bei echtem Offline-Fall: Cache-Fallback ); return; } // Statische Assets (Vite baut mit Content-Hash im Dateinamen): // Network-first, bei Fehler Cache-Fallback (für Offline-Nutzung) e.respondWith( fetch(e.request) .then(response => { if (response.ok) { const clone = response.clone(); caches.open(CACHE_NAME).then(c => c.put(e.request, clone)); } return response; }) .catch(() => caches.match(e.request)) ); }); self.addEventListener('message', e => { if (e.data === 'SKIP_WAITING') self.skipWaiting(); });