1// Service Worker for caching map tiles, fonts, and sprites from the PMTiles server. 2// Cache-first strategy: serve from cache if available, otherwise fetch and cache. 3// This makes repeat visits near-instant since ~2-10MB of tile data is served locally. 4 5const CACHE_NAME = "map-tiles-v1"; 6const TILE_HOST = "map.planner.fahrrad-hotels.com"; 7 8self.addEventListener("install", () => { 9 self.skipWaiting(); 10}); 11 12self.addEventListener("activate", (event) => { 13 // Clean up old cache versions 14 event.waitUntil( 15 caches 16 .keys() 17 .then((keys) => 18 Promise.all( 19 keys 20 .filter((key) => key.startsWith("map-tiles-") && key !== CACHE_NAME) 21 .map((key) => caches.delete(key)) 22 ) 23 ) 24 .then(() => self.clients.claim()) 25 ); 26}); 27 28self.addEventListener("fetch", (event) => { 29 const url = new URL(event.request.url); 30 if (url.hostname !== TILE_HOST) return; 31 32 event.respondWith(handleMapRequest(event.request)); 33}); 34 35async function handleMapRequest(request) { 36 const cache = await caches.open(CACHE_NAME); 37 38 // PMTiles uses Range requests for individual tile fetches. 39 // The Cache API matches on URL only by default, so we encode 40 // the Range header into the cache key to distinguish them. 41 const range = request.headers.get("Range"); 42 const cacheKey = range 43 ? new Request( 44 request.url + 45 (request.url.includes("?") ? "&" : "?") + 46 "_r=" + 47 encodeURIComponent(range) 48 ) 49 : request; 50 51 const cached = await cache.match(cacheKey); 52 if (cached) return cached; 53 54 try { 55 const response = await fetch(request); 56 // Cache successful responses (200 OK and 206 Partial Content for range requests) 57 if (response.ok || response.status === 206) { 58 cache.put(cacheKey, response.clone()); 59 } 60 return response; 61 } catch (err) { 62 // Network failure â return cached version if we somehow have it, otherwise rethrow 63 const fallback = await cache.match(cacheKey); 64 if (fallback) return fallback; 65 throw err; 66 } 67}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.