diff --git a/src/routes/__layout.svelte b/src/routes/__layout.svelte index c01d21e8..da2ad850 100644 --- a/src/routes/__layout.svelte +++ b/src/routes/__layout.svelte @@ -30,9 +30,14 @@ startClient(); - page.subscribe(() => { + let broadcastChannel; + page.subscribe((p) => { try { window.reloadAdSlots(); + broadcastChannel.postMessage({ + type: 'fetch-doc', + path: p.url.pathname, + }); } catch (error) {} }); @@ -46,6 +51,24 @@ }); window.localforage = localforage; await checkLocalSave(); + + if ('serviceWorker' in navigator) { + broadcastChannel = new BroadcastChannel('paimonmoe-sw'); + broadcastChannel.addEventListener('message', (event) => { + if (event.data.type === 'update') window.location.reload(); + }); + + navigator.serviceWorker.register('/service-worker.js').then( + function () { + console.log('service worker registration succeeded'); + }, + function (error) { + console.log('service worker registration failed:', error); + }, + ); + } else { + console.log('service workers are not supported'); + } }); $: segment = $page.url.pathname.substring(1).split('/')[0]; diff --git a/src/service-worker.js b/src/service-worker.js new file mode 100644 index 00000000..31d8f316 --- /dev/null +++ b/src/service-worker.js @@ -0,0 +1,72 @@ +import { version } from '$service-worker'; + +const CACHE = `cache${version}`; +const channel = new BroadcastChannel('paimonmoe-sw'); + +self.addEventListener('install', (event) => { + event.waitUntil(self.skipWaiting()); +}); + +async function fetchAddCache(url) { + try { + const cache = await caches.open(CACHE); + const cachedRes = await cache.match(url); + + if (cachedRes) return; + + const res = await fetch(url); + cache.put(url, res.clone()); + } catch (err) { + console.error(err); + } +} + +self.addEventListener('activate', (event) => { + event.waitUntil( + caches.keys().then(async (keys) => { + let needUpdate = false; + // delete old caches + for (const key of keys) { + if (key !== CACHE) { + await caches.delete(key); + needUpdate = true; + } + } + + self.clients.claim(); + console.log('SW NEED UPDATE', needUpdate); + if (needUpdate) { + channel.postMessage({ + type: 'update', + version, + }); + } + + fetchAddCache('/'); + channel.addEventListener('message', (event) => { + if (event.data.type === 'fetch-doc') { + fetchAddCache(event.data.path); + } + }); + }), + ); +}); + +self.addEventListener('fetch', async (event) => { + if (!event.request.url.startsWith(self.location.origin) || event.request.method !== 'GET') return; + + event.respondWith( + (async () => { + const cache = await caches.open(CACHE); + const cachedRes = await cache.match(event.request); + + if (cachedRes) { + return cachedRes; + } + + const res = await fetch(event.request); + cache.put(event.request, res.clone()); + return res; + })(), + ); +});