/* eslint-disable no-restricted-globals */
const worker = self;
const uniqueName = new Date().toISOString();
const preloadCache = 'preloadCache-' + uniqueName;
const cacheJsonPath = '/assets/cache.json';
const getRandom = () => String(Math.random()).slice(2);
const getRandomQuery = () => "?version=" + getRandom();
const getLatestCacheJson = async () => {
const response = await fetch(cacheJsonPath + getRandomQuery());
return response.json();
};
const getCacheJsonFromCache = async () => {
const cache = await caches.open(preloadCache);
const response = await cache.match(cacheJsonPath);
if (!response) return null;
return response.json();
};
worker.addEventListener('message', event => {
if (event.data && event.data.action !== "check-for-updates") return;
console.log("service-worker: check-for-updates");
checkForUpdates();
});
async function checkForUpdates() {
const [oldJson, newJson] = await Promise.all([getCacheJsonFromCache(), getLatestCacheJson()]);
if (oldJson && oldJson.id !== newJson.id) {
console.log('old version', oldJson.id, 'new version', newJson.id, "updating...");
await addUrlsToTheCache(newJson);
}
}
function sendUpdatedMessageToClients() {
worker.clients.matchAll().then(clients => {
clients.forEach(client => client.postMessage({ "serviceWorkerUpdated": true }));
});
}
worker.addEventListener('activate', event => {
console.log('service-worker', 'activate');
event.waitUntil(checkForUpdates());
});
worker.addEventListener('install', event => {
console.log('service-worker', 'install');
event.waitUntil(
getLatestCacheJson()
.then(addUrlsToTheCache)
.then(() => {
console.log('service-worker', 'install: complete');
})
);
});
let installing = false;
async function addUrlsToTheCache(cacheJsonContent) {
installing = true;
const urlsToCache = cacheJsonContent.preload;
urlsToCache.push(cacheJsonPath);
const names = await caches.keys();
const hadPreviousCache = names.length > 0;
await Promise.all(names.map(name => caches.delete(name)));
const cache = await caches.open(preloadCache);
await addAllToCache(cache, urlsToCache);
await worker.skipWaiting();
console.log('service-worker', 'install: added caches');
installing = false;
if (hadPreviousCache) {
sendUpdatedMessageToClients();
}
}
async function addAllToCache(cache, urls) {
await Promise.all(urls.map(async url => {
const response = await fetch(url + getRandomQuery());
if (!response.ok) {
throw new TypeError('bad response status');
}
return cache.put(url, response);
}));
}
worker.addEventListener('fetch', event => {
const url = event.request.url;
if (!installing && url.startsWith(worker.location.origin)) {
event.respondWith(
caches.match(event.request, {
ignoreSearch: true,
ignoreVary: true
}).then(cachedResponse => {
if (cachedResponse) {
return cachedResponse;
}
return fetch(event.request);
})
);
}
});
if ('serviceWorker' in navigator) {
const serviceWorker = navigator.serviceWorker;
serviceWorker.getRegistrations().then(registrations => {
for (const registration of registrations) {
if (registration.active) {
registration.active.postMessage({ action: "check-for-updates" });
}
}
});
serviceWorker.register('/serviceWorker.js', { scope: '/' });
serviceWorker.addEventListener('message', e => {
if (e.data && e.data.serviceWorkerUpdated) {
window.alert('Updating app to the latest version');
window.location.reload(true);
}
});
}
empty /assets/cache.json (generated by script)
{
"id": "",
"preload": []
}
114300cookie-checkJavascript: service worker