diff --git a/static/serviceworker.js b/static/serviceworker.js index 66372a6..0a934e2 100644 --- a/static/serviceworker.js +++ b/static/serviceworker.js @@ -1,67 +1,26 @@ let version = 'v1::'; let cacheName = 'website'; -let offlinePage = '/offline/'; +let offlinePage = '/offline'; let offlineFundamentals = [offlinePage, '/']; let maxItems = 100; - -function addFundamentals() { - return caches.open(version + cacheName) - .then(cache => cache.addAll(offlineFundamentals)) -} - -// Cache the page(s) that initiate the service worker -function cacheClients() { - return clients.matchAll({ - includeUncontrolled: true - }) - .then(allClients => allClients.map(client => client.url)) - .then(pages => Promise.all([pages, caches.open(cacheName)])) - .then(([pages, cache]) => cache.addAll(pages)) -} - -// Remove caches whose name is no longer valid -function clearInvalidatedCaches() { - return caches.keys() - .then( keys => { - return Promise.all(keys - .filter(key => !key.includes(version)) - .map(key => caches.delete(key)) - ); - }); -} - -function trimCache(name, maxItems) { - return caches.open(name) - .then(cache => Promise.all([cache, cache.keys()])) - // Make sure offlineFundamentals don't get deleted - .then(([cache, keys]) => [ - cache, - keys.filter(key => !offlineFundamentals.includes(key)), - keys.length - maxItems - ]) - .then(([cache, possibleDelete, numToDelete]) => { - // Trim cache until we are of the right size - deleteInProgress = [] - for (let i = 0; i < numToDelete; i++) { - // Keep track of each delete - deleteInProgress.push(cache.delete(possibleDelete[i])); - } - - // Return when everything is resolved - return Promise.all(deleteInProgress); - }) -} - self.addEventListener('install', function (event) { // Cache offline fundamentals - event.waitUntil( - addFundamentals() - .then(() => cacheClients()) - .then(() => skipWaiting()) - ) + event.waitUntil(caches.open(version + cacheName).then(function (cache) { + return cache.addAll(offlineFundamentals); + })); }); +function trimCache(name, maxItems) { + caches.open(name).then(function(cache) { + cache.keys().then(function(keys) { + if (keys.length > maxItems) { + cache.delete(keys[0]).then(trimCache(name, maxItems)); + } + }); + }); +} + // Listens for trimCache command which occurs on page load self.addEventListener('message', event => { if (event.data.command == 'trimCache') { @@ -69,68 +28,65 @@ self.addEventListener('message', event => { } }); + // If the version changes, invalidate the cache self.addEventListener('activate', function (event) { event.waitUntil( - clearInvalidatedCaches() - .then(() => clients.claim()) + caches.keys() + .then(function (keys) { + // Remove caches whose name is no longer valid + return Promise.all(keys + .filter(function (key) { + return key.indexOf(version) !== 0; + }) + .map(function (key) { + return caches.delete(key); + }) + ); + }) ); }); -if (registration.navigationPreload) { - addEventListener('activate', event => { - event.waitUntil( - registration.navigationPreload.enable() - ); - }); -} - // Listen for request events self.addEventListener('fetch', function (event) { - const request = event.request; - - let isRequestType = function(name) { - return request.headers - .get('Accept') - .includes(name); - } + let request = event.request; // Always fetch non-GET requests from the network if (request.method !== 'GET') { - // Present offline page when failed to - // fetch a HTML page - if (isRequestType('text/html')) { - event.respondWith( - fetch(request) - .catch(() => caches.match(offlinePage)) - ); - } + event.respondWith( + fetch(request) + .catch(function () { + return caches.match(offlinePage); + }) + ); return; } + let isRequestType = function(name) { return request.headers.get('Accept').includes(name); } + // Network-first Approach event.respondWith( // Attepmt to grab the latest copy from the network - Promise.resolve(event.preloadResponse) - .then(preloadResponse => preloadResponse || fetch(request)) - .then(response => { + fetch(request).then(function (response) { // If successful, create a copy of the response // and save it to the cache // Note: Ignore badges - if (!request.url.includes("/badges")) { + if (request.url.includes("/badges")) { let cacheCopy = response.clone(); - event.waitUntil( - caches.open(version + cacheName) - .then(cache => cache.put(request, cacheCopy)) - ); + event.waitUntil(caches.open(version + cacheName).then(function (cache) { + return cache.put(request, cacheCopy); + })); } return response; + }).catch(function (error) { + // Otherwise, check the cache. + return caches.match(request).then(function (response) { + // Show offline page if cache misses for HTML pages. + if (isRequestType('text/html')) { + return response || caches.match(offlinePage); + } + return response; + }); }) - // Check the cache - .catch(error => - caches.match(request) - // Show offline page for HTML pages if cache miss - .then(response => isRequestType('text/html')? response || caches.match(offlinePage) : response) - ) ); }); \ No newline at end of file