Service Worker included
This commit is contained in:
parent
6aece9c30b
commit
794ef99609
|
@ -0,0 +1,400 @@
|
||||||
|
const CACHE_VERSION = 2.3;
|
||||||
|
|
||||||
|
const BASE_CACHE_FILES = [
|
||||||
|
'/js/fuse.min.94c78ad70b02749822921660cf4e9f0b3701bc0680c421afb784a78228de0275.js',
|
||||||
|
'/js/helper/getParents.min.1618c696be7c98933f9a92677f518b512a74e55bdbb976b09936b4182e93181b.js',
|
||||||
|
'/css/main.min.css',
|
||||||
|
'/js/helper/fadeinout.min.93a331f96194789a542f33690bbe4f0c102c7e78ffc018217f5a1c33010bad91.js',
|
||||||
|
'/logo.png',
|
||||||
|
'/js/lazysizes.min.31dd6a2d3a1ec0f78a8df007535cf23f03aeb5c70f026e6d6a19dac3b3acc340.js',
|
||||||
|
'/fonts/montserrat-bold.woff2',
|
||||||
|
'/js/enquire.min.dfb99dee1e029d51d6cfb672d847929890b1585402de17f5ed092edd72a688b4.js',
|
||||||
|
'/fonts/montserrat-regular.woff2',
|
||||||
|
'/fonts/merriweather-regular.woff2',
|
||||||
|
|
||||||
|
];
|
||||||
|
|
||||||
|
const OFFLINE_CACHE_FILES = [
|
||||||
|
'/js/fuse.min.94c78ad70b02749822921660cf4e9f0b3701bc0680c421afb784a78228de0275.js',
|
||||||
|
'/js/helper/getParents.min.1618c696be7c98933f9a92677f518b512a74e55bdbb976b09936b4182e93181b.js',
|
||||||
|
'/css/main.min.css',
|
||||||
|
'/js/helper/fadeinout.min.93a331f96194789a542f33690bbe4f0c102c7e78ffc018217f5a1c33010bad91.js',
|
||||||
|
'/logo.png',
|
||||||
|
'/js/lazysizes.min.31dd6a2d3a1ec0f78a8df007535cf23f03aeb5c70f026e6d6a19dac3b3acc340.js',
|
||||||
|
'/fonts/montserrat-bold.woff2',
|
||||||
|
'/offline/'
|
||||||
|
];
|
||||||
|
|
||||||
|
const NOT_FOUND_CACHE_FILES = [
|
||||||
|
'/js/fuse.min.94c78ad70b02749822921660cf4e9f0b3701bc0680c421afb784a78228de0275.js',
|
||||||
|
'/js/helper/getParents.min.1618c696be7c98933f9a92677f518b512a74e55bdbb976b09936b4182e93181b.js',
|
||||||
|
'/css/main.min.css',
|
||||||
|
'/js/helper/fadeinout.min.93a331f96194789a542f33690bbe4f0c102c7e78ffc018217f5a1c33010bad91.js',
|
||||||
|
'/logo.png',
|
||||||
|
'/js/lazysizes.min.31dd6a2d3a1ec0f78a8df007535cf23f03aeb5c70f026e6d6a19dac3b3acc340.js',
|
||||||
|
'/fonts/montserrat-bold.woff2',
|
||||||
|
'/404.html'
|
||||||
|
];
|
||||||
|
|
||||||
|
const OFFLINE_PAGE = '/offline/';
|
||||||
|
const NOT_FOUND_PAGE = '/404.html';
|
||||||
|
|
||||||
|
const CACHE_VERSIONS = {
|
||||||
|
assets: 'assets-v' + CACHE_VERSION,
|
||||||
|
content: 'content-v' + CACHE_VERSION,
|
||||||
|
offline: 'offline-v' + CACHE_VERSION,
|
||||||
|
notFound: '404-v' + CACHE_VERSION,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Define MAX_TTL's in SECONDS for specific file extensions
|
||||||
|
const MAX_TTL = {
|
||||||
|
'/': 3600,
|
||||||
|
html: 3600,
|
||||||
|
json: 86400,
|
||||||
|
js: 86400,
|
||||||
|
css: 86400,
|
||||||
|
};
|
||||||
|
|
||||||
|
const CACHE_BLACKLIST = [
|
||||||
|
//(str) => {
|
||||||
|
// return !str.startsWith('https://yourwebsite.com');
|
||||||
|
//},
|
||||||
|
];
|
||||||
|
|
||||||
|
const SUPPORTED_METHODS = [
|
||||||
|
'GET',
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* isBlackListed
|
||||||
|
* @param {string} url
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
function isBlacklisted(url) {
|
||||||
|
return (CACHE_BLACKLIST.length > 0) ? !CACHE_BLACKLIST.filter((rule) => {
|
||||||
|
if(typeof rule === 'function') {
|
||||||
|
return !rule(url);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}).length : false
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getFileExtension
|
||||||
|
* @param {string} url
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
function getFileExtension(url) {
|
||||||
|
let extension = url.split('.').reverse()[0].split('?')[0];
|
||||||
|
return (extension.endsWith('/')) ? '/' : extension;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getTTL
|
||||||
|
* @param {string} url
|
||||||
|
*/
|
||||||
|
function getTTL(url) {
|
||||||
|
if (typeof url === 'string') {
|
||||||
|
let extension = getFileExtension(url);
|
||||||
|
if (typeof MAX_TTL[extension] === 'number') {
|
||||||
|
return MAX_TTL[extension];
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* installServiceWorker
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
function installServiceWorker() {
|
||||||
|
return Promise.all(
|
||||||
|
[
|
||||||
|
caches.open(CACHE_VERSIONS.assets)
|
||||||
|
.then(
|
||||||
|
(cache) => {
|
||||||
|
return cache.addAll(BASE_CACHE_FILES);
|
||||||
|
}
|
||||||
|
),
|
||||||
|
caches.open(CACHE_VERSIONS.offline)
|
||||||
|
.then(
|
||||||
|
(cache) => {
|
||||||
|
return cache.addAll(OFFLINE_CACHE_FILES);
|
||||||
|
}
|
||||||
|
),
|
||||||
|
caches.open(CACHE_VERSIONS.notFound)
|
||||||
|
.then(
|
||||||
|
(cache) => {
|
||||||
|
return cache.addAll(NOT_FOUND_CACHE_FILES);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
.then(() => {
|
||||||
|
return self.skipWaiting();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cleanupLegacyCache
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
function cleanupLegacyCache() {
|
||||||
|
|
||||||
|
let currentCaches = Object.keys(CACHE_VERSIONS)
|
||||||
|
.map(
|
||||||
|
(key) => {
|
||||||
|
return CACHE_VERSIONS[key];
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return new Promise(
|
||||||
|
(resolve, reject) => {
|
||||||
|
|
||||||
|
caches.keys()
|
||||||
|
.then(
|
||||||
|
(keys) => {
|
||||||
|
return legacyKeys = keys.filter(
|
||||||
|
(key) => {
|
||||||
|
return !~currentCaches.indexOf(key);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then(
|
||||||
|
(legacy) => {
|
||||||
|
if (legacy.length) {
|
||||||
|
Promise.all(
|
||||||
|
legacy.map(
|
||||||
|
(legacyKey) => {
|
||||||
|
return caches.delete(legacyKey)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.then(
|
||||||
|
() => {
|
||||||
|
resolve()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.catch(
|
||||||
|
(err) => {
|
||||||
|
reject(err);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.catch(
|
||||||
|
() => {
|
||||||
|
reject();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function precacheUrl(url) {
|
||||||
|
if(!isBlacklisted(url)) {
|
||||||
|
caches.open(CACHE_VERSIONS.content)
|
||||||
|
.then((cache) => {
|
||||||
|
cache.match(url)
|
||||||
|
.then((response) => {
|
||||||
|
if(!response) {
|
||||||
|
return fetch(url)
|
||||||
|
} else {
|
||||||
|
// already in cache, nothing to do.
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
if(response) {
|
||||||
|
return cache.put(url, response.clone());
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
self.addEventListener(
|
||||||
|
'install', event => {
|
||||||
|
event.waitUntil(
|
||||||
|
Promise.all([
|
||||||
|
installServiceWorker(),
|
||||||
|
self.skipWaiting(),
|
||||||
|
])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// The activate handler takes care of cleaning up old caches.
|
||||||
|
self.addEventListener(
|
||||||
|
'activate', event => {
|
||||||
|
event.waitUntil(
|
||||||
|
Promise.all(
|
||||||
|
[
|
||||||
|
cleanupLegacyCache(),
|
||||||
|
self.clients.claim(),
|
||||||
|
self.skipWaiting(),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
.catch(
|
||||||
|
(err) => {
|
||||||
|
event.skipWaiting();
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
self.addEventListener(
|
||||||
|
'fetch', event => {
|
||||||
|
|
||||||
|
event.respondWith(
|
||||||
|
caches.open(CACHE_VERSIONS.content)
|
||||||
|
.then(
|
||||||
|
(cache) => {
|
||||||
|
|
||||||
|
return cache.match(event.request)
|
||||||
|
.then(
|
||||||
|
(response) => {
|
||||||
|
|
||||||
|
if (response) {
|
||||||
|
|
||||||
|
let headers = response.headers.entries();
|
||||||
|
let date = null;
|
||||||
|
|
||||||
|
for (let pair of headers) {
|
||||||
|
if (pair[0] === 'date') {
|
||||||
|
date = new Date(pair[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (date) {
|
||||||
|
let age = parseInt((new Date().getTime() - date.getTime()) / 1000);
|
||||||
|
let ttl = getTTL(event.request.url);
|
||||||
|
|
||||||
|
if (ttl && age > ttl) {
|
||||||
|
|
||||||
|
return new Promise(
|
||||||
|
(resolve) => {
|
||||||
|
|
||||||
|
return fetch(event.request.clone())
|
||||||
|
.then(
|
||||||
|
(updatedResponse) => {
|
||||||
|
if (updatedResponse) {
|
||||||
|
cache.put(event.request, updatedResponse.clone());
|
||||||
|
resolve(updatedResponse);
|
||||||
|
} else {
|
||||||
|
resolve(response)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.catch(
|
||||||
|
() => {
|
||||||
|
resolve(response);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.catch(
|
||||||
|
(err) => {
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then(
|
||||||
|
(response) => {
|
||||||
|
if (response) {
|
||||||
|
return response;
|
||||||
|
} else {
|
||||||
|
return fetch(event.request.clone())
|
||||||
|
.then(
|
||||||
|
(response) => {
|
||||||
|
|
||||||
|
if(response.status < 400) {
|
||||||
|
if (~SUPPORTED_METHODS.indexOf(event.request.method) && !isBlacklisted(event.request.url)) {
|
||||||
|
cache.put(event.request, response.clone());
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
} else {
|
||||||
|
return caches.open(CACHE_VERSIONS.notFound).then((cache) => {
|
||||||
|
return cache.match(NOT_FOUND_PAGE);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then((response) => {
|
||||||
|
if(response) {
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(
|
||||||
|
() => {
|
||||||
|
|
||||||
|
return caches.open(CACHE_VERSIONS.offline)
|
||||||
|
.then(
|
||||||
|
(offlineCache) => {
|
||||||
|
return offlineCache.match(OFFLINE_PAGE)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.catch(
|
||||||
|
(error) => {
|
||||||
|
console.error(' Error in fetch handler:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
self.addEventListener('message', (event) => {
|
||||||
|
|
||||||
|
if(
|
||||||
|
typeof event.data === 'object' &&
|
||||||
|
typeof event.data.action === 'string'
|
||||||
|
) {
|
||||||
|
switch(event.data.action) {
|
||||||
|
case 'cache' :
|
||||||
|
precacheUrl(event.data.url);
|
||||||
|
break;
|
||||||
|
default :
|
||||||
|
console.log('Unknown action: ' + event.data.action);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
Loading…
Reference in New Issue