<%# The name of the cache to store responses in %> <%# If the cache name changes DevDocs is assumed to be updated %> const cacheName = '<%= service_worker_cache_name %>'; <%# Url's to cache when the service worker is installed %> const urlsToCache = [ '/', '/favicon.ico', '/manifest.json', '<%= service_worker_asset_urls.join "',\n '" %>', '<%= doc_index_urls.join "',\n '" %>', ]; <%# Clone a request with the mode set to 'cors' %> function corsify(request) { const options = { mode: 'cors', }; const keys = [ 'body', 'cache', 'credentials', 'headers', 'integrity', 'keepalive', 'method', 'redirect', 'referrer', 'referrerPolicy', 'signal', 'window', ]; for (const key of keys) { options[key] = request[key]; } return new Request(request.url, options); } <%# Set-up the cache %> self.addEventListener('install', event => { self.skipWaiting(); event.waitUntil( caches.open(cacheName).then(cache => cache.addAll(urlsToCache)), ); }); <%# Remove old caches %> self.addEventListener('activate', event => { event.waitUntil((async () => { const keys = await caches.keys(); const jobs = keys.map(key => key !== cacheName ? caches.delete(key) : Promise.resolve()); return Promise.all(jobs); })()); }); <%# Handle HTTP requests %> self.addEventListener('fetch', event => { event.respondWith((async () => { const cachedResponse = await caches.match(event.request); if (cachedResponse) return cachedResponse; try { const response = await fetch(corsify(event.request)); <%# If the status code is 0 it means the response is opaque %> <%# If the response is opaque it's not possible to read whether it is successful or not, so we assume it is %> if (!response.ok && response.status !== 0) { throw new Error(`The HTTP request failed with status code ${response.status}`); } return response; } catch (err) { const url = new URL(event.request.url); const pathname = url.pathname; const filename = pathname.substr(1 + pathname.lastIndexOf('/')).split(/\#|\?/g)[0]; const extensions = ['.html', '.css', '.js', '.json', '.png', '.ico', '.svg', '.xml']; <%# Attempt to return the index page from the cache if the user is visiting a url like devdocs.io/offline or devdocs.io/javascript/global_objects/array/find %> <%# The index page will make sure the correct documentation or a proper offline page is shown %> if (url.origin === location.origin && !extensions.some(ext => filename.endsWith(ext))) { const cachedIndex = await caches.match('/'); if (cachedIndex) return cachedIndex; } throw err; } })()); });