Skip to content

Instantly share code, notes, and snippets.

@JMPerez
Created October 27, 2018 20:21
Show Gist options
  • Save JMPerez/8ca8d5ffcc0cc45a8b4e1c279efd8a94 to your computer and use it in GitHub Desktop.
Save JMPerez/8ca8d5ffcc0cc45a8b4e1c279efd8a94 to your computer and use it in GitHub Desktop.
An example of a service worker for serving network first, cache second
// 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));
});
@mail4hafij
Copy link

I understand, this is a very basic service worker. But I will point out two things for others to understand before using it.

  1. This will not distinguish cross-origin requests (i.e., google analytics, google maps, other api, etc). It will try to cash that.
  2. In case of POST it will fail and rightly so but it should be handled properly. Meaning, the POST requests should be avoided caching.

@GRY086
Copy link

GRY086 commented May 2, 2024

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