Created
July 1, 2019 09:08
-
-
Save kromakollision/e1b49c1af93d324386536d289305f0f6 to your computer and use it in GitHub Desktop.
This is a basic (untested) service worker setup.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This is a basic (untested) service worker setup. | |
// Thoroughly test all features before using it! | |
// CACHE KEYS | |
// update CACHE_KEY to trigger: | |
// - a new service worker install | |
// - removal of old caches | |
// The new service worker will become active after closing all | |
// website instances where it has been registered | |
const CACHE_KEY = 'cache-v1'; | |
const CACHE_STATIC = `website-${CACHE_KEY}-static`; | |
const CACHE_PRELOAD = `website-${CACHE_KEY}-preload`; | |
const CACHE_DYNAMIC = `website-${CACHE_KEY}-dynamic`; | |
// CACHE ASSETS | |
// supply a list of static assets that need to be cached | |
const cacheStaticAssets = []; | |
// supply a list of static assets that need to be preloaded and cached | |
// for example scripts or assets needed on the next page | |
const cachePreloadAssets = []; | |
// ACTIONS | |
const addStaticCaches = () => | |
caches | |
.open(CACHE_STATIC) | |
.then(cache => cache.addAll(cacheStaticAssets)) | |
.catch(err => | |
console.error('Service worker failed to cache static assets.', err) | |
); | |
const addPreloadCaches = () => | |
caches | |
.open(CACHE_PRELOAD) | |
.then(cache => { | |
// not returning "cache.addAll" allows the preload to fail | |
// since it's not required content for the current page | |
cache.addAll(cachePreloadAssets); | |
}) | |
.catch(err => | |
console.error('Service worker failed to preload static assets.', err) | |
); | |
const removeOldCaches = () => | |
caches | |
.keys() | |
.then(cacheNames => | |
Promise.all( | |
cacheNames.map( | |
cacheName => | |
// delete old caches | |
cacheName.indexOf(CACHE_KEY) === -1 && caches.delete(cacheName) | |
) | |
) | |
) | |
.catch(err => | |
console.error('Service worker failed to remove caches.', err) | |
); | |
const checkDynamicCache = request => | |
caches | |
.open(CACHE_DYNAMIC) | |
.then(cache => | |
cache | |
.match(request) | |
.then( | |
response => | |
// if the request is cached, return the response | |
response || | |
// if not cached, fetch it online and cache it | |
fetch(request) | |
.then(response => { | |
cache.put(request, response.clone()); | |
return response; | |
}) | |
.catch(err => console.error('Service worker fetch failed', err)) | |
) | |
.catch(err => | |
console.error('Service workers failed to match request.', err) | |
) | |
) | |
.catch(err => | |
console.error('Service worker failed to check dynamic cache.', err) | |
); | |
const updateDynamicCache = request => | |
caches | |
.open(CACHE_DYNAMIC) | |
.then(cache => | |
fetch(request) | |
.then(response => cache.put(request, response)) | |
.catch(err => | |
console.error('Service worker failed to fetch cache update.', err) | |
) | |
) | |
.catch(err => | |
console.error('Service worker failed to update dynamic cache.', err) | |
); | |
// EVENTS | |
const onInstall = event => { | |
// console.log('Service worker installed'); | |
event.waitUntil(removeOldCaches()); | |
event.waitUntil(addStaticCaches()); | |
event.waitUntil(addPreloadCaches()); | |
}; | |
const onActivate = event => { | |
// console.log('Service worker activated'); | |
event.waitUntil(removeOldCaches()); | |
}; | |
const onFetch = event => { | |
// console.log('Service worker intercepted fetch', event.request); | |
// skip urls like "chrome-extension://..." | |
if (event.request.url.indexOf('http') !== 0) return; | |
// cache only "GET" requests | |
if (event.request.method !== 'GET') return; | |
// return the cached fetch or fetch it online | |
event.respondWith(checkDynamicCache(event.request)); | |
// after serving the cache, update the cache with a new fetch | |
// to check: does this defeat the purpose of serving a cached version first? It should happen in the background. | |
event.waitUntil(updateDynamicCache(event.request)); | |
}; | |
const onPush = event => { | |
console.log('Service worker received push message', event); | |
}; | |
const onNotificationClick = event => { | |
console.log('Service worker saw user click on notification', event); | |
}; | |
const onBackgroundSync = event => { | |
console.log('Service worker received background sync', event); | |
}; | |
self.addEventListener('install', onInstall); | |
self.addEventListener('activate', onActivate); | |
self.addEventListener('fetch', onFetch); | |
self.addEventListener('push', onPush); | |
self.addEventListener('notificationclick', onNotificationClick); | |
self.addEventListener('sync', onBackgroundSync); | |
self.onsync = function(evt) { | |
console.log('Service worker sync', evt); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment