Skip to content

Commit

Permalink
Do cache-then-network for everything but the main resource
Browse files Browse the repository at this point in the history
This is much snappier!!
  • Loading branch information
domenic committed Jan 12, 2017
1 parent b26845f commit 2ad9488
Showing 1 changed file with 43 additions and 19 deletions.
62 changes: 43 additions & 19 deletions service-worker.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"use strict";
// Largely based on https://css-tricks.com/serviceworker-for-offline/

const cacheKey = "v1";
const cacheKey = "v2";
const toCache = [
"/",
"https://resources.whatwg.org/standard.css",
Expand All @@ -20,28 +19,53 @@ self.onfetch = e => {
return;
}

e.respondWith(
if (needsToBeFresh(e.request)) {
// Since this is a Living Standard, it is imperative that you see the freshest content, so we use a
// network-then-cache strategy.
fetch(e.request).then(res => {
if (!res.ok) {
throw new Error(`${res.url} is responding with ${res.status}; falling back to cache if possible`);
}

const responseForCache = res.clone();
// Do not return this promise; it's OK if caching fails, and we don't want to block on it.
caches.open(cacheKey).then(cache => cache.put(e.request, responseForCache));

return res;
})
.catch(() => {
return caches.match(e.request);
})
);
// network-then-cache strategy for the main content.
e.respondWith(
fetch(e.request).then(res => {
refreshCacheFromNetworkResponse(e.request, res);
return res;
})
.catch(() => {
return caches.match(e.request);
})
);
} else {
// For auxiliary resources, we can use a cache-then-network strategy; it is OK to not get the freshest.
e.respondWith(
caches.match(e.request).then(cachedResponse => {
const networkFetchPromise = fetch(e.request);

// Ignore network fetch or caching errors; they just mean we won't be able to refresh the cache.
networkFetchPromise
.then(res => refreshCacheFromNetworkResponse(e.request, res))
.catch(() => {});

return cachedResponse || networkFetchPromise;
})
);
}
};

self.onactivate = e => {
e.waitUntil(caches.keys().then(keys => {
return Promise.all(keys.filter(key => key !== cacheKey).map(key => caches.delete(key)));
}));
};

function refreshCacheFromNetworkResponse(req, res) {
if (!res.ok) {
throw new Error(`${res.url} is responding with ${res.status}`);
}

const resForCache = res.clone();

// Do not return this promise; it's OK if caching fails, and we don't want to block on it.
caches.open(cacheKey).then(cache => cache.put(req, resForCache));
}

function needsToBeFresh(req) {
const requestURL = new URL(req.url);
return requestURL.origin === location.origin && requestURL.pathname === "/";
}

0 comments on commit 2ad9488

Please sign in to comment.