Skip to content

Instantly share code, notes, and snippets.

@corburn
Last active April 27, 2016 15:28
Show Gist options
  • Save corburn/4ec81440e4f9b320d982 to your computer and use it in GitHub Desktop.
Save corburn/4ec81440e4f9b320d982 to your computer and use it in GitHub Desktop.
Service Worker notes
// https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers
// Feature detection test to make sure service workers are supported before trying to register one.
if ('serviceWorker' in navigator) {
// Scope is an optional USVString that defines the ranges of URL's the service worker controls.
// The default value is the service worker script location.
navigator.serviceWorker.register('/sw-test/sw.js', { scope: '/sw-test/' }).then(function(reg) {
// registration worked
console.log('Registration succeeded. Scope is ' + reg.scope);
}).catch(function(error) {
// registration failed
console.log('Registration failed with ' + error);
});
};
// https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerContainer/register
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('service-worker.js', {scope: './'}).then(function(registration) {
document.querySelector('#status').textContent = 'succeeded';
}).catch(function(error) {
document.querySelector('#status').textContent = error;
});
} else {
// The current browser doesn't support service workers.
var aElement = document.createElement('a');
aElement.href = 'http://www.chromium.org/blink/serviceworker/service-worker-faq';
aElement.textContent = 'unavailable';
document.querySelector('#status').appendChild(aElement);
}
// https://github.com/PolymerElements/platinum-sw
// In order to use <platinum-sw-register>, it's recommended that you create a sw-import.js file in your site's web root.
// The file's only contents should be:
importScripts('bower_components/platinum-sw/service-worker.js');
const CACHE_VERSION = 1;
// Shorthand identifier mapped to specific versioned cache.
var CURRENT_CACHES = {
font: 'font-cache-v' + CACHE_VERSION
};
this.addEventListener('install', function(event) {
event.waitUntil(
caches.open('0.0.1').then(function(cache) {
return cache.addAll([
'/sw-test/',
'/sw-test/index.html',
'/sw-test/style.css',
'/sw-test/app.js',
'/sw-test/image-list.js',
'/sw-test/star-wars-logo.jpg',
'/sw-test/gallery/',
'/sw-test/gallery/bountyHunters.jpg',
'/sw-test/gallery/myLittleVader.jpg',
'/sw-test/gallery/snowTroopers.jpg'
]);
})
);
});
self.addEventListener('activate', function(event) {
var expectedCacheNames = Object.keys(CURRENT_CACHES).map(function(key) {
return CURRENT_CACHES[key];
});
// Promises passed into waitUntil() will block other events until completion,
// so you can rest assured that your clean-up operation will have completed,
// by the time you get your first fetch event on the new cache.
event.waitUntil(
caches.keys().then(function(cacheNames) {
return Promise.all(
cacheNames.map(function(cacheName) {
if (expectedCacheNames.indexOf(cacheName) == -1) {
console.log('Deleting out of date cache:', cacheName);
return caches.delete(cacheName);
}
})
);
})
);
});
this.addEventListener('fetch', function(event) {
// First try the cache
event.respondWith(caches.match(event.request).catch(function() {
// If not in the cache, try the network
return fetch(event.request);
}).then(function(r) {
let response = r;
// Update the cache with the response and send
// a clone of the response to the browser.
caches.open('v1').then(function(cache) {
cache.put(event.request, response);
});
// The response is cloned because the stream can
// only be read once.
return response.clone();
}).catch(function() {
return caches.match('/sw-test/gallery/myLittleVader.jpg');
}));
});
  • HTTPS Required - Service Workers are restricted to running across HTTPS for security reasons.
  • Same Origin Required - Service workers must be from the same domain as for the page/app they are registered.
  • Beware Global Variables - A single service worker can control many pages. Each time a page within your scope is loaded, the service worker is installed against that page and operates on it. Bear in mind therefore that you need to be careful with global variables in the service worker script: each page doesn’t get its own unique worker.

Service worker functions like a proxy server, allowing you to modify requests and responses, replace them with items from its own cache, and more.

Events

  • install - start populating indexeddb and cache site assets
  • activate - Cleanup resources used in previous versions of service worker script. It is now safe to do stuff that would have broken the previous versions while they were running.
  • fetch - retrieve resource managed by the service worker
// You can call this method unconditionally from the controlled page,
// i.e., you don't need to first check whether there's an active registration.
ServiceWorkerContainer.register(scriptURL, options).then(function(ServiceWorkerRegistration) {
  // Do something with ServiceWorkerRegistration.
});

Deleting Old Caches

You are also responsible for periodically purging cache entries. Each browser has a hard limit on the amount of cache storage that a given service worker can use. The browser does its best to manage disk space, but it may delete the Cache storage for an origin. The browser will generally delete all of the data for an origin or none of the data for an origin. Make sure to version caches by name and use the caches only from the version of the ServiceWorker that they can safely operate on.

Updating Service Workers

Chrome has chrome://inspect/#service-workers, which shows current service worker activity and storage on a device, and chrome://serviceworker-internals, which shows more detail and allows you to start/stop/debug the worker process.

Resources

Specification Development Repository

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment