/** * MYP Service Worker * ================= * * Service Worker für das Mercedes-Benz 3D-Druck-Management-System * Bietet Offline-Funktionalität und Caching für bessere Performance */ const CACHE_NAME = 'myp-v1.0.0'; const STATIC_CACHE_NAME = 'myp-static-v1.0.0'; const DYNAMIC_CACHE_NAME = 'myp-dynamic-v1.0.0'; // Statische Ressourcen, die immer gecacht werden sollen const STATIC_ASSETS = [ '/', '/static/css/tailwind.min.css', '/static/css/dark-light-unified.css', '/static/fontawesome/css/all.min.css', '/static/js/jobs-safety-fix.js', '/static/manifest.json', '/static/favicon.svg', '/static/icons/icon-192.png', '/static/icons/icon-512.png' ]; // API-Endpunkte, die gecacht werden können const CACHEABLE_APIS = [ '/api/printers', '/api/jobs', '/api/stats' ]; // Installation des Service Workers self.addEventListener('install', event => { console.log('🔧 MYP Service Worker wird installiert...'); event.waitUntil( caches.open(STATIC_CACHE_NAME) .then(cache => { console.log('📦 Statische Assets werden gecacht...'); return cache.addAll(STATIC_ASSETS); }) .then(() => { console.log('✅ MYP Service Worker erfolgreich installiert'); return self.skipWaiting(); }) .catch(error => { console.error('❌ Fehler bei Service Worker Installation:', error); }) ); }); // Aktivierung des Service Workers self.addEventListener('activate', event => { console.log('🚀 MYP Service Worker wird aktiviert...'); event.waitUntil( caches.keys() .then(cacheNames => { return Promise.all( cacheNames.map(cacheName => { // Alte Caches löschen if (cacheName !== STATIC_CACHE_NAME && cacheName !== DYNAMIC_CACHE_NAME && cacheName !== CACHE_NAME) { console.log('🗑️ Lösche alten Cache:', cacheName); return caches.delete(cacheName); } }) ); }) .then(() => { console.log('✅ MYP Service Worker aktiviert'); return self.clients.claim(); }) ); }); // Fetch-Event Handler für Caching-Strategien self.addEventListener('fetch', event => { const request = event.request; const url = new URL(request.url); // Nur GET-Requests cachen if (request.method !== 'GET') { return; } // Statische Assets: Cache First if (STATIC_ASSETS.some(asset => url.pathname.endsWith(asset) || url.pathname === asset)) { event.respondWith(cacheFirst(request)); return; } // API-Endpunkte: Network First mit Cache Fallback if (CACHEABLE_APIS.some(api => url.pathname.startsWith(api))) { event.respondWith(networkFirst(request)); return; } // Statische Dateien (CSS, JS, Bilder): Cache First if (url.pathname.startsWith('/static/')) { event.respondWith(cacheFirst(request)); return; } // HTML-Seiten: Network First if (request.headers.get('accept').includes('text/html')) { event.respondWith(networkFirst(request)); return; } // Alle anderen Requests: Network Only event.respondWith(fetch(request)); }); /** * Cache First Strategie * Versucht zuerst aus dem Cache zu laden, dann aus dem Netzwerk */ async function cacheFirst(request) { try { const cache = await caches.open(STATIC_CACHE_NAME); const cachedResponse = await cache.match(request); if (cachedResponse) { console.log('📦 Aus Cache geladen:', request.url); return cachedResponse; } const networkResponse = await fetch(request); if (networkResponse.ok) { cache.put(request, networkResponse.clone()); console.log('🌐 Aus Netzwerk geladen und gecacht:', request.url); } return networkResponse; } catch (error) { console.error('❌ Cache First Fehler:', error); // Fallback für kritische Ressourcen if (request.url.includes('tailwind.min.css')) { return new Response('/* Offline CSS Fallback */', { headers: { 'Content-Type': 'text/css' } }); } throw error; } } /** * Network First Strategie * Versucht zuerst aus dem Netzwerk zu laden, dann aus dem Cache */ async function networkFirst(request) { try { const networkResponse = await fetch(request); if (networkResponse.ok) { const cache = await caches.open(DYNAMIC_CACHE_NAME); cache.put(request, networkResponse.clone()); console.log('🌐 Aus Netzwerk geladen:', request.url); return networkResponse; } throw new Error(`Network response not ok: ${networkResponse.status}`); } catch (error) { console.log('📦 Netzwerk nicht verfügbar, versuche Cache:', request.url); const cache = await caches.open(DYNAMIC_CACHE_NAME); const cachedResponse = await cache.match(request); if (cachedResponse) { console.log('📦 Aus Cache geladen (Offline):', request.url); return cachedResponse; } // Offline-Fallback für API-Requests if (request.url.includes('/api/')) { return new Response(JSON.stringify({ success: false, error: 'Offline - Keine Verbindung zum Server', offline: true }), { status: 503, headers: { 'Content-Type': 'application/json' } }); } // Offline-Fallback für HTML-Seiten if (request.headers.get('accept').includes('text/html')) { const offlineHtml = `