Files
filestash/client/worker/sw_cache.js
2020-12-22 21:29:01 +11:00

123 lines
3.6 KiB
JavaScript

const CACHE_NAME = "v0.3";
/*
* Control everything going through the wire, applying different
* strategy for caching, fetching resources
*/
self.addEventListener("fetch", function(event){
if(is_a_ressource(event.request)){
return event.respondWith(cacheFirstStrategy(event));
}else if(is_an_api_call(event.request)){
return event;
}else if(is_an_index(event.request)){
return event.respondWith(cacheFirstStrategy(event));
}else{
return event;
}
});
/*
* When a new service worker is coming in, we need to do a bit of
* cleanup to get rid of the rotten cache
*/
self.addEventListener("activate", function(event){
vacuum(event);
});
self.addEventListener("error", function(err){
console.error(err);
});
/*
* When a newly installed service worker is coming in, we want to use it
* straight away (make it active). By default it would be in a "waiting state"
*/
self.addEventListener("install", function(){
caches.open(CACHE_NAME).then(function(cache) {
return cache.addAll([
"/",
"/api/config"
]);
});
if (self.skipWaiting) { self.skipWaiting(); }
});
function is_a_ressource(request){
const p = _pathname(request);
if(["assets", "manifest.json", "favicon.ico"].indexOf(p[0]) !== -1){
return true;
} else if(p[0] === "api" && (p[1] === "config")){
return true;
}
return false;
}
function is_an_api_call(request){
return _pathname(request)[0] === "api" ? true : false;
}
function is_an_index(request){
return ["files", "view", "login", "logout", ""].indexOf(_pathname(request)[0]) >= 0? true : false;
}
////////////////////////////////////////
// HELPERS
////////////////////////////////////////
function vacuum(event){
return event.waitUntil(
caches.keys().then(function(cachesName){
return Promise.all(cachesName.map(function(cacheName){
if(cacheName !== CACHE_NAME){
return caches.delete(cacheName);
}
}));
})
);
}
function _pathname(request){
//eslint-disable-next-line no-useless-escape
return request.url.replace(/^http[s]?:\/\/[^\/]*\//, "").split("/");
}
/*
* strategy is cache first:
* 1. use whatever is in the cache
* 2. perform the network call to update the cache
*/
function cacheFirstStrategy(event){
return caches.open(CACHE_NAME).then(function(cache){
return cache.match(event.request).then(function(response){
if(!response){
return fetchAndCache(event);
}
fetchAndCache(event).catch(nil);
return response;
});
});
function fetchAndCache(event){
// A request is a stream and can only be consumed once. Since we are consuming this
// once by cache and once by the browser for fetch, we need to clone the response as
// seen on https://developers.google.com/web/fundamentals/getting-started/primers/service-workers
return fetch(event.request)
.then(function(response){
if(!response || response.status !== 200){ return response; }
// A response is a stream and can only because we want the browser to consume the
// response as well as the cache consuming the response, we need to clone it
const responseClone = response.clone();
caches.open(CACHE_NAME).then(function(cache){
cache.put(event.request, responseClone);
});
return response;
});
}
function nil(){}
}