Created
October 24, 2018 06:59
-
-
Save olpeh/e88889726c3207c05dcc39fd0b3503e0 to your computer and use it in GitHub Desktop.
Service Worker Sample Code (NOT A FULLY WORKING EXAMPLE, USE AT YOUR OWN RISK)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function() { | |
'use strict'; | |
// Make this a kill switch by reading this from config | |
window.ServiceWorkerEnabled = true; | |
if ('serviceWorker' in navigator) { | |
if (window.ServiceWorkerEnabled) { | |
// Delay registration until after the page has loaded, to ensure that our | |
// precaching requests don't degrade the first visit experience. | |
// See https://developers.google.com/web/fundamentals/instant-and-offline/service-worker/registration | |
window.addEventListener('load', function() { | |
// Your service-worker.js *must* be located at the top-level directory relative to your site. | |
// It won't be able to control pages unless it's located at the same level or higher than them. | |
// *Don't* register service worker file in, e.g., a scripts/ sub-directory! | |
// See https://github.com/slightlyoff/ServiceWorker/issues/468 | |
navigator.serviceWorker | |
.register('/service-worker.js') | |
.then(function(reg) { | |
// updatefound is fired if service-worker.js changes. | |
reg.onupdatefound = function() { | |
// The updatefound event implies that reg.installing is set; see | |
// https://w3c.github.io/ServiceWorker/#service-worker-registration-updatefound-event | |
var installingWorker = reg.installing; | |
installingWorker.onstatechange = function() { | |
switch (installingWorker.state) { | |
case 'installed': | |
if ( | |
navigator.serviceWorker.controller | |
) { | |
// At this point, the old content will have been purged and the fresh content will | |
// have been added to the cache. | |
// It's the perfect time to display a "New content is available; please refresh." | |
// message in the page's interface. | |
console.log( | |
'New or updated content is available.' | |
); | |
} else { | |
// At this point, everything has been precached. | |
// It's the perfect time to display a "Content is cached for offline use." message. | |
console.log( | |
'Content is now available offline!' | |
); | |
} | |
break; | |
case 'redundant': | |
console.error( | |
'The installing service worker became redundant.' | |
); | |
break; | |
} | |
}; | |
}; | |
}) | |
.catch(function(e) { | |
console.error( | |
'Error during service worker registration:', | |
e | |
); | |
}); | |
}); | |
} else { | |
// Kill switch triggering unregistration | |
console.log( | |
'Kill switch triggered, going to unregister service workers for this site!' | |
); | |
navigator.serviceWorker | |
.getRegistrations() | |
.then(function(registrations) { | |
registrations.forEach(function(registration) { | |
registration.unregister(); | |
}); | |
}); | |
} | |
} | |
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function() { | |
'use strict'; | |
/* global cacheName, urlsToCacheKeys */ | |
function offlinePage() { | |
// Serve "offline" page if it couldn't be fetched | |
// from cache or network | |
return caches | |
.match('/assets/error/offline.html') | |
.then(function(response) { | |
// Cache hit - return response | |
if (response) { | |
return response; | |
} else { | |
console.warn('No offline.html found in the caches'); | |
} | |
}); | |
} | |
function offlineImage() { | |
return caches | |
.match('/assets/error/offline.svg') | |
.then(function(response) { | |
// Cache hit - return response | |
if (response) { | |
return response; | |
} else { | |
console.warn('No offline.svg found in the caches'); | |
} | |
}); | |
} | |
function customFetch(fetchRequest) { | |
var url = fetchRequest.url, | |
acceptType = fetchRequest.headers.get('Accept'); | |
return fetch(fetchRequest) | |
.then(function(response) { | |
console.log('Fetch: ' + url); | |
// Check if we received a valid response | |
if ( | |
!response || | |
!(response.status === 200 || response.status === 0) || | |
!(response.type === 'basic' || response.type === 'opaque') | |
) { | |
console.warn( | |
'Response was not ok:', | |
response.type, | |
response | |
); | |
return response; | |
} | |
// IMPORTANT: Clone the response. A response is a stream | |
// and because we want the browser to consume the response | |
// as well as the cache consuming the response, we need | |
// to clone it so we have two streams. | |
var responseToCache = response.clone(); | |
caches.open(cacheName).then(function(cache) { | |
console.log( | |
'Adding response to ' + cacheName + ' for ' + url | |
); | |
cache.put(url, responseToCache); | |
}); | |
return response; | |
}) | |
.catch(function(e) { | |
console.error('Error was caught!', e); | |
if (acceptType.includes('text/html')) { | |
return offlinePage(); | |
} else if (acceptType.includes('image')) { | |
console.log('Trying to respond with offlineImage'); | |
return offlineImage(); | |
} else { | |
throw e; | |
} | |
}); | |
} | |
function shouldEventBeHandled(event) { | |
// Create your own logic here | |
// You probably should not cache everything | |
return true; | |
} | |
self.addEventListener('fetch', function(event) { | |
if (event.request.method === 'GET') { | |
// Should we call event.respondWith() inside this fetch event handler? | |
// This needs to be determined synchronously, which will give other fetch | |
// handlers a chance to handle the request if need be. | |
var shouldRespond; | |
// First, remove all the ignored parameters and hash fragment, and see if we | |
// have that URL in our cache. If so, great! shouldRespond will be true. | |
var url = event.request.url; | |
shouldRespond = | |
urlsToCacheKeys.has(url) || shouldEventBeHandled(event); | |
console.log('Should respond for ' + url + ' was ' + shouldRespond); | |
if (shouldRespond) { | |
return event.respondWith( | |
caches | |
.match(urlsToCacheKeys.get(url)) | |
.then(function(response) { | |
// Cache hit - return response | |
if (response) { | |
console.log('Cache hit: ' + url); | |
return response; | |
} | |
console.log( | |
'Couldn\'t serve response for "%s" from cache, going to try to fetch, if we are online', | |
event.request.url | |
); | |
return customFetch(event.request); | |
}) | |
); | |
} | |
// ignore | |
} | |
}); | |
self.customFetch = customFetch; | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment