Service Workers

What is service worker?

ServiceWorker is a background worker, it gives us a JavaScript context to add features such as push messaging, background sync, geofencing and network control.

In terms of network control, it acts like a proxy server sitting on the client, you get to decide what to do on a request-by-request basis. You can use this to make stuff work faster, offline, or build new features.

Basically, it gives you control over web page so that you can select which elements to cache. One problem with service worker is that it only works on localhost or with https:// requests.

How to install service worker?

Some of the new browser supports service workers. First of all we need to register service worker in a way, so that it does not affect unsupported browsers.

Following piece of code register the service worker and make sure it works on all supported browser without breaking existing functionality.

if (navigator.serviceWorker) {
    navigator.serviceWorker.register('./service-worker.js')
        .then(function (registration) {
            console.log(registration);
        })
        .catch(function (e) {
            console.error(e);
        })
} else {
    console.log('Service Worker is not supported in this browser.');
}​

In the above code ./service-worker.js is the path of the Service Worker. You can view all the registered Service Workers by going to chrome://serviceworker-internals.

Install event in service worker

First of all, we will look at the install event. When browser sees the service worker for the first time this event is triggered. This event is the best place to cache app shell.

I want to use the install stage to pre-cache some static assets (images, CSS, JavaScript) that are used by many pages on my website.

I can speed up the page loading times by grabbing these out of cache, instead of fetching from the network on subsequent page loads.

self.addEventListener('install', event => {
  // Do install stuff
});​

Tell the install event to hang on and not to complete until I’ve done what I need to do by using event.waitUntil. Open the appropriate cache, and stick the static assets in it by using Cache.addAll.

The service worker implements the CacheStorage interface, which makes the caches property available globally in our service worker.

Let's take a look at the cache example.

var CACHE_VERSION = 'app-v1';
var CACHE_FILES = [
    '/',
    'js/app.js',
    'css/app.css'
];
self.addEventListener('install', function (event) {
    event.waitUntil(
        caches.open(CACHE_VERSION)
            .then(function (cache) {
                console.log('Opened cache');
                return cache.addAll(CACHE_FILES);
            })
    );
});

Activate event in service worker

This event occurs when the old version of service worker file is gone.

Here you can make changes that would have broken the old version, such as deleting old caches and migrating data.

self.addEventListener('activate', function(event) {
  // Do activate stuff: This will come later on.
});​

Fetch event in service worker

The magic of our service worker is really going to happen when fetch events are triggered.

We can respond to fetches in different ways by telling the browser to always try to fetch certain assets from the network. It avoids the request for cached static assets.

Following piece of code is used to deal with fetch event.

self.addEventListener('fetch', event => {
  // … Perhaps respond to this fetch in a useful way?
});​