64 lines
1.8 KiB
JavaScript
64 lines
1.8 KiB
JavaScript
import { readdirSync, writeFileSync } from 'node:fs'
|
|
import { relative, resolve } from 'node:path'
|
|
|
|
const distDirectory = resolve('dist')
|
|
|
|
function listFiles(directory) {
|
|
return readdirSync(directory, { withFileTypes: true }).flatMap((entry) => {
|
|
const path = resolve(directory, entry.name)
|
|
return entry.isDirectory() ? listFiles(path) : [path]
|
|
})
|
|
}
|
|
|
|
const assets = listFiles(distDirectory)
|
|
.map((path) => `/${relative(distDirectory, path).replaceAll('\\', '/')}`)
|
|
.filter((path) => path !== '/service-worker.js')
|
|
.sort()
|
|
const cacheName = `chronicle-${Date.now()}`
|
|
const source = `const CACHE_NAME = ${JSON.stringify(cacheName)}
|
|
const APP_ASSETS = ${JSON.stringify(assets, null, 2)}
|
|
|
|
self.addEventListener('install', (event) => {
|
|
event.waitUntil(
|
|
caches.open(CACHE_NAME)
|
|
.then((cache) => cache.addAll(APP_ASSETS))
|
|
.then(() => self.skipWaiting()),
|
|
)
|
|
})
|
|
|
|
self.addEventListener('activate', (event) => {
|
|
event.waitUntil(
|
|
caches.keys()
|
|
.then((keys) => Promise.all(
|
|
keys.filter((key) => key !== CACHE_NAME).map((key) => caches.delete(key)),
|
|
))
|
|
.then(() => self.clients.claim()),
|
|
)
|
|
})
|
|
|
|
self.addEventListener('fetch', (event) => {
|
|
const requestUrl = new URL(event.request.url)
|
|
if (
|
|
event.request.method !== 'GET'
|
|
|| requestUrl.origin !== self.location.origin
|
|
|| requestUrl.pathname.startsWith('/api/')
|
|
) {
|
|
return
|
|
}
|
|
|
|
event.respondWith(
|
|
caches.match(event.request).then((cached) => {
|
|
if (cached) return cached
|
|
return fetch(event.request).catch(() => (
|
|
event.request.mode === 'navigate'
|
|
? caches.match('/index.html')
|
|
: Response.error()
|
|
))
|
|
}),
|
|
)
|
|
})
|
|
`
|
|
|
|
writeFileSync(resolve(distDirectory, 'service-worker.js'), source)
|
|
console.log(`Offline app shell generated with ${assets.length} files.`)
|