generators/app/templates/src/sw.js
/* globals global */
/* eslint-disable no-console */
const DEBUG = true;
// When the user navigates to the site, the browser tries to redownload the script file that defined the service worker in the background.
// If there is even a byte's difference in the service worker file compared to what it currently has, it considers it 'new'.
const { assets } = global.serviceWorkerOption;
const CACHE_NAME = new Date().toISOString();
let assetsToCache = [...assets, './'];
assetsToCache = assetsToCache.map(path => {
return new URL(path, global.location).toString();
});
// When the service worker is first added to a computer.
self.addEventListener('install', event => {
// Perform install steps.
if (DEBUG) {
console.log('[SW] Install event');
}
// Add core website files to cache during serviceworker installation.
event.waitUntil(
global.caches
.open(CACHE_NAME)
.then(cache => {
return cache.addAll(assetsToCache);
})
.then(() => {
if (DEBUG) {
console.log('Cached assets: main', assetsToCache);
}
})
.catch(error => {
console.error(error);
throw error;
})
);
});
// After the install event.
self.addEventListener('activate', event => {
if (DEBUG) {
console.log('[SW] Activate event');
}
// Clean the caches
event.waitUntil(
global.caches.keys().then(cacheNames => {
return Promise.all(
cacheNames.map(cacheName => {
// Delete the caches that are not the current one.
if (cacheName.indexOf(CACHE_NAME) === 0) {
return null;
}
return global.caches.delete(cacheName);
})
);
})
);
});
self.addEventListener('message', event => {
switch (event.data.action) {
case 'skipWaiting':
if (self.skipWaiting) {
self.skipWaiting();
self.clients.claim();
}
break;
default:
break;
}
});
self.addEventListener('fetch', event => {
const request = event.request;
// Ignore not GET request.
if (request.method !== 'GET') {
if (DEBUG) {
console.log(`[SW] Ignore non GET request ${request.method}`);
}
return;
}
const requestUrl = new URL(request.url);
// Ignore different origin.
if (requestUrl.origin !== location.origin) {
if (DEBUG) {
console.log(`[SW] Ignore different origin ${requestUrl.origin}`);
}
return;
}
const resource = global.caches.match(request).then(response => {
if (response) {
if (DEBUG) {
console.log(`[SW] fetch URL ${requestUrl.href} from cache`);
}
return response;
}
// Load and cache known assets.
return fetch(request, {
credentials: 'include'
})
.then(responseNetwork => {
if (!responseNetwork || !responseNetwork.ok) {
if (DEBUG) {
console.log(
`[SW] URL [${requestUrl.toString()}] wrong responseNetwork: ${responseNetwork.status} ${
responseNetwork.type
}`
);
}
return responseNetwork;
}
if (DEBUG) {
console.log(`[SW] URL ${requestUrl.href} fetched`);
}
const responseCache = responseNetwork.clone();
global.caches
.open(CACHE_NAME)
.then(cache => {
return cache.put(request, responseCache);
})
.then(() => {
if (DEBUG) {
console.log(`[SW] Cache asset: ${requestUrl.href}`);
}
})
.catch(() => {
if (DEBUG) {
console.error(`[SW] Error while caching asset: ${requestUrl.href}`);
}
});
return responseNetwork;
})
.catch(() => {
// Passing through the request.
if (event.request.mode === 'navigate') {
return fetch(event.request);
}
if (DEBUG) {
console.error(`[SW] Error while fetching ${event.request}. No match inside sw.js so far. Returning null.`);
}
return null;
});
});
event.respondWith(resource);
});