Activate Service Workers Faster

By  on  

Service workers are great for many purposes:  speed, offline, cache control, and more.  You can view many code service worker usage samples over at the Service Worker Cookbook, if you're so interested.  One of those recipes, Immediate Claim, is as important and useful as it provides a way to claim your service worker more quickly, meaning you can receive fetch events faster.

You can liken the following code quickening to DOMContentLoaded (commonly known as domready) vs. the old load event -- set processing into motion more quickly.  The trick involves the service worker's install and activate events:

// Install event - cache files (...or not)
// Be sure to call skipWaiting()!
self.addEventListener('install', function(event) {
  event.waitUntil(
	caches.open('my-cache').then(function(cache) {
        // Important to `return` the promise here to have `skipWaiting()`
        // fire after the cache has been updated.
        return cache.addAll([/* file1.jpg, file2.png, ... */]);
    }).then(function() {
      // `skipWaiting()` forces the waiting ServiceWorker to become the
      // active ServiceWorker, triggering the `onactivate` event.
      // Together with `Clients.claim()` this allows a worker to take effect
      // immediately in the client(s).
      return self.skipWaiting();
    })
  );
});

// Activate event
// Be sure to call self.clients.claim()
self.addEventListener('activate', function(event) {
	// `claim()` sets this worker as the active worker for all clients that
	// match the workers scope and triggers an `oncontrollerchange` event for
	// the clients.
	return self.clients.claim();
});

Ultimately returning the skipWaiting() from the install event triggers the activate event, activating the service worker immediately and allowing your service worker to work with fetch events and other service worker capabilities.  Service workers require a navigation event (reloading the page, going to a new page, etc.) to activate which is why this trick is so handy.

Look forward to more service worker tips and examples on the blog over the coming months!

Recent Features

  • By
    Conquering Impostor Syndrome

    Two years ago I documented my struggles with Imposter Syndrome and the response was immense.  I received messages of support and commiseration from new web developers, veteran engineers, and even persons of all experience levels in other professions.  I've even caught myself reading the post...

  • By
    How I Stopped WordPress Comment Spam

    I love almost every part of being a tech blogger:  learning, preaching, bantering, researching.  The one part about blogging that I absolutely loathe:  dealing with SPAM comments.  For the past two years, my blog has registered 8,000+ SPAM comments per day.  PER DAY.  Bloating my database...

Incredible Demos

  • By
    LightFace:  Facebook Lightbox for MooTools

    One of the web components I've always loved has been Facebook's modal dialog.  This "lightbox" isn't like others:  no dark overlay, no obnoxious animating to size, and it doesn't try to do "too much."  With Facebook's dialog in mind, I've created LightFace:  a Facebook lightbox...

  • By
    Build a Calendar Using PHP, XHTML, and CSS

    One of the website features my customers love to provider their web users is an online dynamic calendar. An online calendar can be used for events, upcoming product specials, memos, and anything else you can think of. I've taken some time to completely...

Discussion

  1. Şafak Gür

    MDN samples always use event.waitUntil on activate. Does returning a promise like you did does the same?

    • Paul

      No – using waitUntil() just means all the items have been cached before the service worker is activated. Using skipWaiting() means that you don’t have to do a second re-load of the site to actually activate the service worker. The second reload for me is the only annoying thing about service workers. It’s amazing how much searching of the internet I had to do to find out how to overwrite the default behaviour.

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!