UNPKG

@enplug/scripts

Version:
119 lines (103 loc) 4.08 kB
/** * Service worker responsible for providing offline support to the WebPlayer * @author Michal Drewniak (michal@enplug.com) */ "use strict"; /** * 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); })); });