100 lines
3.3 KiB
JavaScript
100 lines
3.3 KiB
JavaScript
|
import { VERSION as CACHE_NAME } from '@/constants';
|
||
|
|
||
|
const DEBUG = (process.env.NODE_ENV !== 'production');
|
||
|
|
||
|
// Define the assets to cache
|
||
|
const { assets } = global.serviceWorkerOption;
|
||
|
let assetsToCache = [...assets, './'];
|
||
|
assetsToCache = assetsToCache.map(
|
||
|
path => new URL(path, global.location).toString(),
|
||
|
);
|
||
|
assetsToCache = assetsToCache.filter(
|
||
|
// Remove some assets from cache, such as Webpack hot-reload stuff
|
||
|
url => !url.endsWith('hot-update.json'),
|
||
|
);
|
||
|
|
||
|
// Define the locations from which we allow caching
|
||
|
const ALLOW_CACHING_FROM = [
|
||
|
global.location.origin,
|
||
|
];
|
||
|
|
||
|
global.self.addEventListener('install', (event) => {
|
||
|
DEBUG && console.log('SW: installing…');
|
||
|
event.waitUntil(
|
||
|
global.caches.open(CACHE_NAME)
|
||
|
.then((cache) => {
|
||
|
DEBUG && console.log('SW: cache opened.');
|
||
|
cache.addAll(assetsToCache).then(
|
||
|
() => {
|
||
|
if (DEBUG) {
|
||
|
console.log(`SW: cached assets ${assetsToCache}.`);
|
||
|
console.log('SW: successfully installed!');
|
||
|
}
|
||
|
return global.self.skipWaiting(); // Immediately update the SW
|
||
|
},
|
||
|
);
|
||
|
}),
|
||
|
);
|
||
|
});
|
||
|
|
||
|
global.self.addEventListener('activate', (event) => {
|
||
|
DEBUG && console.log('SW: activating…');
|
||
|
|
||
|
event.waitUntil(
|
||
|
// Delete all caches but the current one
|
||
|
global.caches.keys().then(
|
||
|
cacheNames => Promise.all(
|
||
|
cacheNames.map((cacheName) => {
|
||
|
if (cacheName.indexOf(CACHE_NAME) !== 0) {
|
||
|
DEBUG && console.log(`SW: Deleting unused cache ${cacheName}.`);
|
||
|
return global.caches.delete(cacheName);
|
||
|
}
|
||
|
return null;
|
||
|
}),
|
||
|
).then(() => DEBUG && console.log('SW: activated!')),
|
||
|
),
|
||
|
);
|
||
|
});
|
||
|
|
||
|
global.self.addEventListener('fetch', (event) => {
|
||
|
const { request } = event;
|
||
|
|
||
|
// Do not touch requests which are not GET
|
||
|
if (request.method !== 'GET') {
|
||
|
DEBUG && console.log(`SW: ignore non-GET request: ${request.method}`);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Do not touch requests from a different origin
|
||
|
const requestURL = new URL(request.url);
|
||
|
if (ALLOW_CACHING_FROM.indexOf(requestURL.origin) === -1) {
|
||
|
DEBUG && console.log(`SW: ignore different origin ${requestURL.origin}`);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Never touch requests going from / to the API
|
||
|
if (requestURL.pathname.startsWith('/api')) {
|
||
|
// Note that if API is on a different location, it will be ignored by
|
||
|
// the previous rule.
|
||
|
DEBUG && console.log(`SW: ignore API call ${requestURL.pathname}`);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// For the other requests, try to match it in the cache, otherwise do a
|
||
|
// network call
|
||
|
const resource = global.caches.open(CACHE_NAME).then(
|
||
|
cache => cache.match(request).then(
|
||
|
(response) => {
|
||
|
if (response) {
|
||
|
DEBUG && console.log(`SW: serving ${request.url} from cache`);
|
||
|
return response;
|
||
|
}
|
||
|
|
||
|
DEBUG && console.log(`SW: no match in cache for ${request.url}, using network`);
|
||
|
return fetch(request);
|
||
|
},
|
||
|
),
|
||
|
);
|
||
|
event.respondWith(resource);
|
||
|
});
|