manage-your-printer/static/js/css-cache-service-worker.js
2025-06-04 10:03:22 +02:00

372 lines
10 KiB
JavaScript

/**
* MYP Platform - CSS Caching Service Worker
* Intelligentes Caching für optimierte CSS-Performance
*/
const CACHE_NAME = 'myp-css-cache-v1.0';
const CSS_CACHE_NAME = 'myp-css-resources-v1.0';
// Kritische CSS-Ressourcen für sofortiges Caching
const CRITICAL_CSS_RESOURCES = [
'/static/css/caching-optimizations.css',
'/static/css/optimization-animations.css',
'/static/css/glassmorphism.css',
'/static/css/professional-theme.css',
'/static/css/tailwind.min.css'
];
// Nicht-kritische CSS-Ressourcen für Prefetching
const NON_CRITICAL_CSS_RESOURCES = [
'/static/css/components.css',
'/static/css/printers.css',
'/static/fontawesome/css/all.min.css'
];
// CSS-spezifische Konfiguration
const CSS_CACHE_CONFIG = {
maxAge: 24 * 60 * 60 * 1000, // 24 Stunden
maxEntries: 50,
networkTimeoutSeconds: 5
};
// Service Worker Installation
self.addEventListener('install', event => {
console.log('[CSS-SW] Service Worker wird installiert...');
event.waitUntil(
caches.open(CSS_CACHE_NAME)
.then(cache => {
console.log('[CSS-SW] Kritische CSS-Ressourcen werden gecacht...');
return cache.addAll(CRITICAL_CSS_RESOURCES);
})
.then(() => {
console.log('[CSS-SW] Installation abgeschlossen');
return self.skipWaiting();
})
.catch(error => {
console.error('[CSS-SW] Fehler bei Installation:', error);
})
);
});
// Service Worker Aktivierung
self.addEventListener('activate', event => {
console.log('[CSS-SW] Service Worker wird aktiviert...');
event.waitUntil(
caches.keys()
.then(cacheNames => {
return Promise.all(
cacheNames.map(cacheName => {
// Alte Caches löschen
if (cacheName !== CACHE_NAME && cacheName !== CSS_CACHE_NAME) {
console.log('[CSS-SW] Alter Cache wird gelöscht:', cacheName);
return caches.delete(cacheName);
}
})
);
})
.then(() => {
console.log('[CSS-SW] Aktivierung abgeschlossen');
return self.clients.claim();
})
.then(() => {
// Nicht-kritische Ressourcen im Hintergrund prefetchen
return prefetchNonCriticalResources();
})
);
});
// CSS-Request-Behandlung mit Cache-First-Strategie
self.addEventListener('fetch', event => {
const { request } = event;
// Nur CSS-Requests verarbeiten
if (!request.url.includes('.css') && !request.url.includes('/static/css/')) {
return;
}
event.respondWith(
handleCSSRequest(request)
);
});
// CSS-Request-Handler mit intelligenter Cache-Strategie
async function handleCSSRequest(request) {
const url = new URL(request.url);
try {
// 1. Cache-First für CSS-Dateien
const cachedResponse = await caches.match(request);
if (cachedResponse) {
console.log('[CSS-SW] Cache-Hit für:', url.pathname);
// Hintergrund-Update für kritische Ressourcen
if (CRITICAL_CSS_RESOURCES.some(resource => url.pathname.includes(resource))) {
updateCacheInBackground(request);
}
return cachedResponse;
}
// 2. Network-Request mit Timeout
const networkResponse = await fetchWithTimeout(request, CSS_CACHE_CONFIG.networkTimeoutSeconds * 1000);
if (networkResponse && networkResponse.ok) {
// Response für Cache klonen
const responseToCache = networkResponse.clone();
// Asynchron cachen
cacheResponse(request, responseToCache);
console.log('[CSS-SW] Network-Response für:', url.pathname);
return networkResponse;
}
// 3. Fallback für kritische CSS
return await getFallbackCSS(request);
} catch (error) {
console.error('[CSS-SW] Fehler bei CSS-Request:', error);
return await getFallbackCSS(request);
}
}
// Network-Request mit Timeout
function fetchWithTimeout(request, timeout) {
return new Promise((resolve, reject) => {
const timer = setTimeout(() => {
reject(new Error('Network timeout'));
}, timeout);
fetch(request)
.then(response => {
clearTimeout(timer);
resolve(response);
})
.catch(error => {
clearTimeout(timer);
reject(error);
});
});
}
// Response asynchron cachen
async function cacheResponse(request, response) {
try {
const cache = await caches.open(CSS_CACHE_NAME);
await cache.put(request, response);
// Cache-Größe prüfen und ggf. alte Einträge löschen
await maintainCacheSize();
} catch (error) {
console.error('[CSS-SW] Fehler beim Cachen:', error);
}
}
// Cache-Größe überwachen und bereinigen
async function maintainCacheSize() {
try {
const cache = await caches.open(CSS_CACHE_NAME);
const requests = await cache.keys();
if (requests.length > CSS_CACHE_CONFIG.maxEntries) {
console.log('[CSS-SW] Cache-Bereinigung wird durchgeführt...');
// Älteste Einträge löschen (LRU-ähnlich)
const excessCount = requests.length - CSS_CACHE_CONFIG.maxEntries;
for (let i = 0; i < excessCount; i++) {
await cache.delete(requests[i]);
}
}
} catch (error) {
console.error('[CSS-SW] Fehler bei Cache-Wartung:', error);
}
}
// Hintergrund-Update für kritische Ressourcen
async function updateCacheInBackground(request) {
try {
const response = await fetch(request);
if (response && response.ok) {
const cache = await caches.open(CSS_CACHE_NAME);
await cache.put(request, response.clone());
console.log('[CSS-SW] Hintergrund-Update für:', request.url);
}
} catch (error) {
console.log('[CSS-SW] Hintergrund-Update fehlgeschlagen:', error);
}
}
// Fallback-CSS für kritische Requests
async function getFallbackCSS(request) {
const url = new URL(request.url);
// Minimales Fallback-CSS für kritische Komponenten
const fallbackCSS = `
/* Fallback CSS für Offline-Nutzung */
body {
font-family: system-ui, sans-serif;
margin: 0;
padding: 20px;
background: #f8fafc;
color: #1f2937;
}
.offline-notice {
background: #fef3c7;
border: 1px solid #f59e0b;
border-radius: 8px;
padding: 16px;
margin-bottom: 20px;
text-align: center;
}
.btn {
background: #0073ce;
color: white;
border: none;
padding: 8px 16px;
border-radius: 4px;
cursor: pointer;
}
.card {
background: white;
border: 1px solid #e5e7eb;
border-radius: 8px;
padding: 16px;
margin-bottom: 16px;
}
`;
return new Response(fallbackCSS, {
headers: {
'Content-Type': 'text/css',
'Cache-Control': 'no-cache'
}
});
}
// Nicht-kritische Ressourcen im Hintergrund prefetchen
async function prefetchNonCriticalResources() {
try {
const cache = await caches.open(CSS_CACHE_NAME);
for (const resource of NON_CRITICAL_CSS_RESOURCES) {
try {
const request = new Request(resource);
const cachedResponse = await cache.match(request);
if (!cachedResponse) {
const response = await fetch(request);
if (response && response.ok) {
await cache.put(request, response);
console.log('[CSS-SW] Prefetch erfolgreich für:', resource);
}
}
} catch (error) {
console.log('[CSS-SW] Prefetch fehlgeschlagen für:', resource);
}
}
} catch (error) {
console.error('[CSS-SW] Fehler beim Prefetching:', error);
}
}
// Message-Handler für Cache-Management
self.addEventListener('message', event => {
const { type, data } = event.data;
switch (type) {
case 'SKIP_WAITING':
self.skipWaiting();
break;
case 'CLEAR_CSS_CACHE':
clearCSSCache().then(() => {
event.ports[0].postMessage({ success: true });
});
break;
case 'PREFETCH_CSS':
prefetchSpecificCSS(data.urls).then(() => {
event.ports[0].postMessage({ success: true });
});
break;
case 'GET_CACHE_STATS':
getCacheStats().then(stats => {
event.ports[0].postMessage(stats);
});
break;
}
});
// CSS-Cache leeren
async function clearCSSCache() {
try {
await caches.delete(CSS_CACHE_NAME);
console.log('[CSS-SW] CSS-Cache wurde geleert');
} catch (error) {
console.error('[CSS-SW] Fehler beim Leeren des CSS-Cache:', error);
}
}
// Spezifische CSS-Dateien prefetchen
async function prefetchSpecificCSS(urls) {
try {
const cache = await caches.open(CSS_CACHE_NAME);
for (const url of urls) {
try {
const response = await fetch(url);
if (response && response.ok) {
await cache.put(url, response);
console.log('[CSS-SW] Spezifisches Prefetch für:', url);
}
} catch (error) {
console.log('[CSS-SW] Spezifisches Prefetch fehlgeschlagen für:', url);
}
}
} catch (error) {
console.error('[CSS-SW] Fehler beim spezifischen Prefetching:', error);
}
}
// Cache-Statistiken abrufen
async function getCacheStats() {
try {
const cache = await caches.open(CSS_CACHE_NAME);
const requests = await cache.keys();
return {
cssEntries: requests.length,
maxEntries: CSS_CACHE_CONFIG.maxEntries,
cacheUtilization: (requests.length / CSS_CACHE_CONFIG.maxEntries) * 100,
cachedUrls: requests.map(req => req.url)
};
} catch (error) {
console.error('[CSS-SW] Fehler beim Abrufen der Cache-Stats:', error);
return { error: error.message };
}
}
// Performance-Monitoring
self.addEventListener('install', () => {
console.log('[CSS-SW] Installation gestartet um:', new Date().toISOString());
});
self.addEventListener('activate', () => {
console.log('[CSS-SW] Aktivierung abgeschlossen um:', new Date().toISOString());
});
// Globaler Error-Handler
self.addEventListener('error', event => {
console.error('[CSS-SW] Globaler Fehler:', event.error);
});
self.addEventListener('unhandledrejection', event => {
console.error('[CSS-SW] Unbehandelte Promise-Rejection:', event.reason);
});
console.log('[CSS-SW] CSS-Caching Service Worker geladen');