Initial commit: Lageplan v1.0 - Next.js 15.5, React 19
This commit is contained in:
94
public/sw.js
Normal file
94
public/sw.js
Normal file
@@ -0,0 +1,94 @@
|
||||
const TILE_CACHE = 'lageplan-tiles-v2'
|
||||
const STATIC_CACHE = 'lageplan-static-v2'
|
||||
const APP_CACHE = 'lageplan-app-v2'
|
||||
|
||||
// Pre-cache essential app shell on install
|
||||
self.addEventListener('install', (event) => {
|
||||
event.waitUntil(
|
||||
caches.open(APP_CACHE).then((cache) =>
|
||||
cache.addAll([
|
||||
'/app',
|
||||
'/logo.svg',
|
||||
'/logo-icon.png',
|
||||
'/manifest.json',
|
||||
]).catch(() => {})
|
||||
)
|
||||
)
|
||||
self.skipWaiting()
|
||||
})
|
||||
|
||||
// Cache strategy: Network First for API, Cache First for tiles, Stale While Revalidate for static assets
|
||||
self.addEventListener('fetch', (event) => {
|
||||
const url = event.request.url
|
||||
const { pathname } = new URL(url)
|
||||
|
||||
// Skip non-GET requests
|
||||
if (event.request.method !== 'GET') return
|
||||
|
||||
// API requests: network only (don't cache dynamic data)
|
||||
if (pathname.startsWith('/api/')) return
|
||||
|
||||
// Cache map tiles from OpenStreetMap (Cache First)
|
||||
if (url.includes('tile.openstreetmap.org') || url.includes('api.maptiler.com')) {
|
||||
event.respondWith(
|
||||
caches.open(TILE_CACHE).then((cache) =>
|
||||
cache.match(event.request).then((cached) => {
|
||||
if (cached) return cached
|
||||
return fetch(event.request).then((response) => {
|
||||
if (response.ok) {
|
||||
cache.put(event.request, response.clone())
|
||||
}
|
||||
return response
|
||||
}).catch(() => new Response('', { status: 503 }))
|
||||
})
|
||||
)
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
// Static assets (JS, CSS, images): Stale While Revalidate
|
||||
if (pathname.match(/\.(js|css|png|jpg|jpeg|svg|ico|woff2?)$/)) {
|
||||
event.respondWith(
|
||||
caches.open(STATIC_CACHE).then((cache) =>
|
||||
cache.match(event.request).then((cached) => {
|
||||
const fetchPromise = fetch(event.request).then((response) => {
|
||||
if (response.ok) cache.put(event.request, response.clone())
|
||||
return response
|
||||
}).catch(() => cached || new Response('', { status: 503 }))
|
||||
return cached || fetchPromise
|
||||
})
|
||||
)
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
// App pages: Network First with cache fallback
|
||||
if (pathname === '/app' || pathname === '/' || pathname.startsWith('/app')) {
|
||||
event.respondWith(
|
||||
fetch(event.request).then((response) => {
|
||||
if (response.ok) {
|
||||
const clone = response.clone()
|
||||
caches.open(APP_CACHE).then((cache) => cache.put(event.request, clone))
|
||||
}
|
||||
return response
|
||||
}).catch(() =>
|
||||
caches.match(event.request).then((cached) => cached || caches.match('/app'))
|
||||
)
|
||||
)
|
||||
return
|
||||
}
|
||||
})
|
||||
|
||||
// Clean old caches on activation
|
||||
self.addEventListener('activate', (event) => {
|
||||
const currentCaches = [TILE_CACHE, STATIC_CACHE, APP_CACHE]
|
||||
event.waitUntil(
|
||||
caches.keys().then((keys) =>
|
||||
Promise.all(
|
||||
keys
|
||||
.filter((k) => !currentCaches.includes(k))
|
||||
.map((k) => caches.delete(k))
|
||||
)
|
||||
).then(() => self.clients.claim())
|
||||
)
|
||||
})
|
||||
Reference in New Issue
Block a user