From a647b08d5b3686fae531379fffd7ab0f01da49bb Mon Sep 17 00:00:00 2001 From: Carl Date: Thu, 14 Nov 2024 06:30:38 +0100 Subject: [PATCH] Add service worker (#93) --- public/icons/maskable.png | Bin 4977 -> 7564 bytes public/manifest.json | 25 ++++++++++----- public/service-worker.js | 63 ++++++++++++++++++++++++++++++++++++++ src/components/style.js | 3 ++ src/serviceWorker.js | 23 ++++++++++++++ 5 files changed, 106 insertions(+), 8 deletions(-) create mode 100644 public/service-worker.js create mode 100644 src/serviceWorker.js diff --git a/public/icons/maskable.png b/public/icons/maskable.png index 02020ffb763132a9346c4f165c2320c0dcf63dbb..930d74f5372a87c5ba301e8c99c5c57544129837 100644 GIT binary patch literal 7564 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 regex.test(url)); +} + +// Install event: skipWaiting allows for more aggressive unloading +self.addEventListener("install", (event) => { + self.skipWaiting(); +}); + +// Activate event: Clean up old caches +self.addEventListener("activate", (event) => { + event.waitUntil( + caches.keys().then((cacheNames) => { + return Promise.all( + cacheNames.filter((cacheName) => cacheName !== DYNAMIC_CACHE). + map((cacheName) => caches.delete(cacheName)), + ); + }), + ); + self.clients.claim(); +}); + +// Fetch event: Serve cached assets if available; otherwise, fetch from network and cache the response +self.addEventListener("fetch", (event) => { + const requestUrl = event.request.url; + + // Check if the request URL should be cached dynamically + if (shouldCache(requestUrl)) { + // Network-first strategy for URLs in the matching array + event.respondWith( + fetch(event.request).then((response) => { + // Clone and store the response in the dynamic cache + return caches.open(DYNAMIC_CACHE).then((cache) => { + cache.put(event.request, response.clone()); + return response; + }); + }).catch(() => caches.match(event.request)), // Fallback to cache on network failure + ); + } else { + // Cache-first strategy for other requests (but do not cache if not matching) + event.respondWith( + caches.match(event.request).then((cachedResponse) => { + if (cachedResponse) return cachedResponse; + + // Fetch from network without caching the result + return fetch(event.request); + }), + ); + } +}); diff --git a/src/components/style.js b/src/components/style.js index 66e39fe..56ec8c6 100644 --- a/src/components/style.js +++ b/src/components/style.js @@ -2,3 +2,6 @@ import "/assets/css/root.scss"; import "/assets/css/page.scss"; import "/assets/css/navbar.scss"; import "/assets/css/footer.scss"; +import {registerServiceWorker} from '../serviceWorker.js'; + +registerServiceWorker(); diff --git a/src/serviceWorker.js b/src/serviceWorker.js new file mode 100644 index 0000000..b060df2 --- /dev/null +++ b/src/serviceWorker.js @@ -0,0 +1,23 @@ +export function registerServiceWorker() { + if ('serviceWorker' in navigator) { + navigator.serviceWorker + .register('/service-worker.js') + .then((registration) => { + console.log('Service Worker registered with scope:', registration.scope); + + // Listen for updates to the service worker + registration.onupdatefound = () => { + const newWorker = registration.installing; + if (newWorker) { + newWorker.onstatechange = () => { + if (newWorker.state === 'installed' && navigator.serviceWorker.controller) { + // New content is available, notify the user or auto-refresh + console.log('New Service Worker found. Refresh for updates.'); + } + }; + } + }; + }) + .catch((error) => console.error('Service Worker registration failed:', error)); + } +}