121 lines
3.1 KiB
JavaScript
121 lines
3.1 KiB
JavaScript
|
function log(...params) {
|
||
|
console.log.apply(this, [...["%c[SW]: %c", "color: #f4b942;", "color:unset;"], ...params])
|
||
|
}
|
||
|
|
||
|
const CACHE = "offline";
|
||
|
|
||
|
let precacheFiles = [
|
||
|
"/",
|
||
|
"/main.js",
|
||
|
"/main.css",
|
||
|
"/serviceworker.js"
|
||
|
]
|
||
|
|
||
|
//Install stage sets up the cache-array to configure pre-cache content
|
||
|
self.addEventListener('install', (evt) => {
|
||
|
log('The service worker is being installed.');
|
||
|
evt.waitUntil(precache().then(() => {
|
||
|
log('Skip waiting on install');
|
||
|
}).catch(log).then(() => self.skipWaiting()));
|
||
|
});
|
||
|
|
||
|
//allow sw to control of current page
|
||
|
self.addEventListener('activate', (event) => {
|
||
|
log('Claiming clients for current page');
|
||
|
return self.clients.claim();
|
||
|
});
|
||
|
|
||
|
self.addEventListener('message', (event) => {
|
||
|
if (event.data === "clear_cache") {
|
||
|
log("Clearing cache");
|
||
|
caches.delete(CACHE);
|
||
|
}
|
||
|
|
||
|
if (event.data === "update_index") {
|
||
|
log("Updating index");
|
||
|
event.waitUntil(caches.open(CACHE).then((cache) => {
|
||
|
return cache.addAll(["/", "/index.html"]).then(() => {
|
||
|
event.ports[0].postMessage("reload");
|
||
|
});
|
||
|
}))
|
||
|
}
|
||
|
});
|
||
|
|
||
|
var Types;
|
||
|
(function (Types) {
|
||
|
Types[Types["CACHE"] = 0] = "CACHE";
|
||
|
Types[Types["NOCACHE"] = 1] = "NOCACHE";
|
||
|
Types[Types["REFRESH"] = 2] = "REFRESH";
|
||
|
})(Types || (Types = {}));
|
||
|
|
||
|
let rules = [
|
||
|
{
|
||
|
match: (url) => {
|
||
|
return url.indexOf("/api/") >= 0;
|
||
|
},
|
||
|
type: Types.NOCACHE
|
||
|
},
|
||
|
{
|
||
|
match: (url) => {
|
||
|
return url.indexOf("/version_hash") >= 0;
|
||
|
},
|
||
|
type: Types.NOCACHE
|
||
|
},
|
||
|
{
|
||
|
match: () => {
|
||
|
return true;
|
||
|
},
|
||
|
type: Types.REFRESH
|
||
|
}
|
||
|
]
|
||
|
|
||
|
self.addEventListener('fetch', (evt) => {
|
||
|
if (evt.request.method != 'GET') return; // Dont care about POST requests
|
||
|
let rule = rules.find(rule => rule.match(evt.request.url));
|
||
|
evt.respondWith((async () => {
|
||
|
log("Cache:", Types[rule.type]);
|
||
|
switch (rule.type) {
|
||
|
case Types.CACHE:
|
||
|
return fromCache(evt.request);
|
||
|
case Types.REFRESH:
|
||
|
return refresh(evt.request).then(r => {
|
||
|
evt.waitUntil(r.refresh.catch(_ => { }));
|
||
|
return r.result;
|
||
|
});
|
||
|
case Types.NOCACHE:
|
||
|
return fetch(evt.request);
|
||
|
}
|
||
|
})());
|
||
|
});
|
||
|
|
||
|
async function fromCache(request) {
|
||
|
let cache = await caches.open(CACHE);
|
||
|
let matching = await cache.match(request);
|
||
|
if (matching)
|
||
|
return matching
|
||
|
|
||
|
let res = await fetch(request.clone());
|
||
|
await cache.put(request, res);
|
||
|
return await cache.match(request);
|
||
|
}
|
||
|
|
||
|
async function refresh(request) {
|
||
|
let cache = await caches.open(CACHE);
|
||
|
let web = fetch(request.clone()).then(res => {
|
||
|
return cache.put(request, res).then(() => {
|
||
|
return cache.match(request);
|
||
|
})
|
||
|
})
|
||
|
let matching = await cache.match(request);
|
||
|
|
||
|
return {
|
||
|
result: matching ? matching : web,
|
||
|
refresh: web
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function precache() {
|
||
|
return caches.open(CACHE).then(function (cache) {
|
||
|
return cache.addAll(precacheFiles);
|
||
|
});
|
||
|
}
|