@enplug/scripts
Version:
Enplug scripts
119 lines (103 loc) • 4.08 kB
JavaScript
/**
* Service worker responsible for providing offline support to the WebPlayer
* @author Michal Drewniak (michal@enplug.com)
*/
;
/**
* Offline support configuration.
* @type {Object}
* @property {string} cacheVersion - Version of the cache. This should be updated any time we want
* the previous version of the cache removed.
* @property {string} cacheName - Name of the cache. This is usually the same as the application
* name or ID.
* @property {Array.<string>} = A list of static URLs which should be cached.
* @property {Object.<string, number>} - A mapping of URLs (or their parts) to time in minutes.
* The URL denotes for which locations cached responses should be refreshed. Time denotes
* after which time (in minutes), given response should be refreshed. Time set to 0 means that
* a given response should never be cached.
*/
var config = <% config %>;
// End of config. There shouldn't be any need to edit code below.
/**
* Installs service worker and adds static resources to cache.
*/
self.addEventListener('install', function (event) {
event.waitUntil(caches.open(config.cacheVersion).then((cache) => {
return cache.addAll(config.staticResources)
.then(() => {
console.log(`[<% app_name %>|enplug-offline-worker] Offline support service worker v${config.cacheVersion} installed.`);
self.skipWaiting();
})
.catch((error) => {
console.warn(`[<% app_name %>|enplug-offline-worker] Error adding static resources to cache ${config.cacheVersion}.`, error);
})
}));
});
/**
* Activate phase. Clears all non-whitelisted cache.
*/
self.addEventListener('activate', (event) => {
var cacheWhitelist = [config.cacheVersion];
event.waitUntil(
caches.keys().then(function (cacheNames) {
return Promise.all(
cacheNames.map(function (cacheName) {
if (cacheWhitelist.indexOf(cacheName) === -1) {
console.log(`[<% app_name %>|enplug-offline-worker] Deleting cache ${cacheName}`);
return caches.delete(cacheName);
}
})
).then(() => self.clients.claim());
})
);
});
/**
* Captures requests and either exectures request to the server or returns a cached version.
*/
self.addEventListener("fetch", event => {
// Ignore POST requests
if (event.request.method === 'POST') {
return false;
}
// Get rid of the app token to generalize URL for caching. Having unique URLs for each request
// will only make the cache get bigger over time.
var cacheUrl = event.request.url.replace(/\?apptoken=[^&]*/g, '');
if (cacheUrl.startsWith('blob:') || cacheUrl.endsWith('.mp4')) {
console.log(`[<% app_name %>|offline] Caching prevented: URL starts with blob: or ends with .mp4.`);
return false;
}
for (const noCacheUrl of config.noCacheUrls) {
if (event.request.url.indexOf(noCacheUrl) >= 0) {
return false;
}
}
// We need to explicitly change the reqest to CORS request so that cross-domain resources
// get properly cached.
var fetchRequest = new Request(event.request.url, {
mode: "cors"
});
event.respondWith(fetch(fetchRequest).then((response) => {
// Fetching new data resulted in a valid response. Cache it.
var responseToCache = response.clone();
caches.open(config.cacheVersion).then(
(cache) => {
// Cache response and update the time of caching this particular request.
if (!response || response.status !== 200 || (response.type !== "basic" && response.type !== "cors")) {
console.log(`[<% app_name %> Cached ${cacheUrl}.`);
cache.put(cacheUrl, responseToCache);
} else {
return caches.match(cacheUrl);
}
},
(error) => {
console.warn(`[<% app_name %> Unable to cache ${cacheUrl}`, error)
}
);
// Return the response.
return response;
})
.catch(() => {
console.log(`[<% app_name %> Unable to fetch ${cacheUrl}. Attempting to return it from cache.`);
return caches.match(cacheUrl);
}));
});