ruk·si

🍦 JavaScript
Service Workers

Updated at 2015-07-26 16:30

A service worker is a script that is run by your browser in the background, separate from a web page, opening the door to features which don't need a web page or user interaction.

JavaScript workers cannot access the DOM directly.

To install a service worker for your site, you need to register it, which you do in your page's JavaScript.

After the activation step, the service worker will control all pages that fall under its scope, though the page that registered the service worker for the first time won't be controlled until it's loaded again.

HTTPS in needed if you use service workers. Otherwise others can highjack connections by manipulating responses. Only register service workers on pages served over HTTPS.

Registering a service worker. Registering multiple times is ok.

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/sw.js').then(function(registration) {
    console.log(
      'ServiceWorker registration successful with scope: ',
      registration.scope
    );
  }).catch(function(err) {
    console.log('ServiceWorker registration failed: ', err);
  });
}

If a worker registers, but then doesn't appear in chrome://inspect/#service-workers or chrome://serviceworker-internals, it's likely its failed to install due to an exception being thrown, or a rejected promise being passed to event.waitUntil.

To work around this, go to chrome://serviceworker-internals and check "Opens the DevTools window for service worker on start for debugging", and put a debugger; statement at the start of your install event. This, along with "Pause on uncaught exceptions", should reveal the issue.

One subtlety with the register method is the location of the service worker file. You'll notice in this case that the service worker file is at the root of the domain. This means that the service worker's scope will be the entire origin. In other words, this service worker will receive fetch events for everything on this domain. If we register the service worker file at /example/sw.js, then the service worker would only see fetch events for pages whose URL starts with /example.

Example service worker script:

var CACHE_NAME = 'my-site-cache-v1';
var urlsToCache = [
  '/index.html',
  '/styles/main.css',
  '/script/main.js'
];
self.addEventListener('install', function(event) {
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then(function(cache) {
        console.log('Opened cache');
        return cache.addAll(urlsToCache);
      })
  );
});

How to update a service worker:

  1. Update the JS file.
  2. As the file has byte size difference, client will download it.
  3. The new worker will be used the second time the page is loaded, not first.
  4. New service worker enters "waiting" state.
  5. Old service worker will be used as long as there are pages of your site open.
  6. New service worker launches "activate" event.

Sources