Created
October 27, 2018 20:21
-
-
Save JMPerez/8ca8d5ffcc0cc45a8b4e1c279efd8a94 to your computer and use it in GitHub Desktop.
An example of a service worker for serving network first, cache second
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
// the cache version gets updated every time there is a new deployment | |
const CACHE_VERSION = 10; | |
const CURRENT_CACHE = `main-${CACHE_VERSION}`; | |
// these are the routes we are going to cache for offline support | |
const cacheFiles = ['/', '/about-me/', '/projects/', '/offline/']; | |
// on activation we clean up the previously registered service workers | |
self.addEventListener('activate', evt => | |
evt.waitUntil( | |
caches.keys().then(cacheNames => { | |
return Promise.all( | |
cacheNames.map(cacheName => { | |
if (cacheName !== CURRENT_CACHE) { | |
return caches.delete(cacheName); | |
} | |
}) | |
); | |
}) | |
) | |
); | |
// on install we download the routes we want to cache for offline | |
self.addEventListener('install', evt => | |
evt.waitUntil( | |
caches.open(CURRENT_CACHE).then(cache => { | |
return cache.addAll(cacheFiles); | |
}) | |
) | |
); | |
// fetch the resource from the network | |
const fromNetwork = (request, timeout) => | |
new Promise((fulfill, reject) => { | |
const timeoutId = setTimeout(reject, timeout); | |
fetch(request).then(response => { | |
clearTimeout(timeoutId); | |
fulfill(response); | |
update(request); | |
}, reject); | |
}); | |
// fetch the resource from the browser cache | |
const fromCache = request => | |
caches | |
.open(CURRENT_CACHE) | |
.then(cache => | |
cache | |
.match(request) | |
.then(matching => matching || cache.match('/offline/')) | |
); | |
// cache the current page to make it available for offline | |
const update = request => | |
caches | |
.open(CURRENT_CACHE) | |
.then(cache => | |
fetch(request).then(response => cache.put(request, response)) | |
); | |
// general strategy when making a request (eg if online try to fetch it | |
// from the network with a timeout, if something fails serve from cache) | |
self.addEventListener('fetch', evt => { | |
evt.respondWith( | |
fromNetwork(evt.request, 10000).catch(() => fromCache(evt.request)) | |
); | |
evt.waitUntil(update(evt.request)); | |
}); |
The default caching behavior of my P.W.A. had completely smothered my ability to update a line of code! This network-first implementation is exactly what I needed. "It feels like I'm caching nohtin' at all!"
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I understand, this is a very basic service worker. But I will point out two things for others to understand before using it.