Files
VBB-Status-Web-App/service-worker.js
T
2026-07-10 12:16:47 +02:00

109 lines
3.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
const CACHE_NAME = 'vbb-status-v37.5.0';
// App-Shell: nur Dateien, die wirklich existieren!
// (Der alte SW listete eine nicht existierende Font-Datei – dadurch
// schlug cache.addAll() komplett fehl und der SW wurde NIE installiert.)
const urlsToCache = [
'/',
'/index.html',
'/js/api.js',
'/js/transitous.js',
'/js/app.js',
'/js/livemap.js',
'/js/changelog.js',
'/js/extras.js',
'/styles.css',
'/manifest.json',
'/images/favicon.png'
];
// Installation: Dateien einzeln cachen, damit EIN Fehler nicht alles blockiert
self.addEventListener('install', event => {
event.waitUntil(
caches.open(CACHE_NAME).then(cache =>
Promise.allSettled(
urlsToCache.map(url =>
cache.add(url).catch(err => console.warn('SW: Konnte nicht cachen:', url, err))
)
)
)
);
self.skipWaiting();
});
// Aktivierung: alte Caches aufräumen
self.addEventListener('activate', event => {
event.waitUntil(
caches.keys().then(cacheNames =>
Promise.all(
cacheNames.map(cacheName => {
if (cacheName !== CACHE_NAME) {
console.log('SW: Alter Cache wird gelöscht:', cacheName);
return caches.delete(cacheName);
}
})
)
)
);
self.clients.claim();
});
// Fetch-Strategie:
// - API-Requests (cross-origin, z.B. v6.vbb.transport.rest, Karten-Tiles):
// NIE vom SW cachen -> direkt durchreichen. Das Rate-Limit- und
// Caching-Management macht die App selbst (apiFetch in js/api.js, Endpoints in js/transitous.js).
// - App-Shell (HTML/JS/CSS): Network-first mit Cache-Fallback.
// So bekommen Nutzer nach einem Deploy sofort die neue Version,
// und offline funktioniert die App trotzdem weiter.
self.addEventListener('fetch', event => {
const request = event.request;
// Nur GET-Requests behandeln
if (request.method !== 'GET') return;
const url = new URL(request.url);
// Leaflet vom CDN: versionierte, unveränderliche Dateien -> cache-first.
// Beim zweiten Besuch lädt die Karte damit ohne Netzwerk-Roundtrip.
if (url.hostname === 'unpkg.com' && url.pathname.includes('leaflet@')) {
event.respondWith(
caches.match(request).then(cached =>
cached || fetch(request).then(response => {
if (response && response.status === 200) {
const copy = response.clone();
caches.open(CACHE_NAME).then(cache => cache.put(request, copy));
}
return response;
})
)
);
return;
}
// Übriges Cross-Origin (API, Karten-Tiles): nicht anfassen
if (url.origin !== self.location.origin) return;
event.respondWith(
fetch(request)
.then(response => {
// Gültige Antwort -> Cache aktualisieren und zurückgeben
if (response && response.status === 200 && response.type === 'basic') {
const responseToCache = response.clone();
caches.open(CACHE_NAME).then(cache => cache.put(request, responseToCache));
}
return response;
})
.catch(() =>
// Offline -> aus dem Cache bedienen
caches.match(request).then(cached => {
if (cached) return cached;
// Navigations-Fallback auf index.html
if (request.mode === 'navigate') {
return caches.match('/index.html');
}
return new Response('Offline', { status: 503, statusText: 'Offline' });
})
)
);
});