Write Your First Service Worker in 5 Minutes

By  on  

What is a service worker?

A service worker is a little file that will allow you to cache files and other assets on a user's machine. How is this different from server-side caching? Because the assets are stored on a user's machine, rather than a server, there is no need to go across a network. This offers a lot of gains for your app's reliability and speed. Since the app is being served from a cache, there's no need to go over the network which can take up a lot of time.

Why this will help your app

Adding a service worker will not only help increase the speed of your app, it'll offer a reliability that your users haven't seen before. By removing the immediate need for internet access, we can help anyone with a spotty internet connection -- and really everyone has a spotty internet connection.


The service worker lifecycle looks a bit like this:

  1. Install
  2. Activate
  3. Fetch

Let's look at these events individually.


Prior to the install event, your application does not have a service worker. The browser will detect the registration event from your code and install the service worker. Your service worker will contain a function called oninstall that will handle which files are cached onto the user's machine.


The activate event is fired after the service worker is installed and ready to go. This is a really good place to do clean up on old files and caches that you don't need anymore. However, for this example, we won't do anything with our activate event.


This is where our service worker really shines. When a fetch request is made, our service worker will intercept it using a function aptly named fetch. Your service worker can look for a similar fetch request from our cache, or send the request onward.

The interesting thing about the service worker lifecycle is that activate and fetch don't necessarily run back-to-back. Fetch will only run when there is a fetch event to intercept, so it could be some time between the activate event and a fetch event. During that time the service worker is idle.

Now that we have a solid understanding of the service worker lifecycle, let's take a look at a sample.

Sample service worker

For this example, let's use FayePI. This is a little API I wrote to help women learn to build dynamic websites, and the documentation page uses a very simple service worker.

Before a service worker can ever be installed, we have to add a registration function to our app's code.

// index.js

if(navigator.serviceWorker) {

That will usually go in your index.js file to be fired when the page is loaded. That's the only reference to your service worker in your app-specific code.

Now we'll have a separate file for our service worker.

// serviceworker.js

self.oninstall = function() {
    caches.open('fayeFrontEndV1').then(function(cache) {
        cache.addAll([ / ... / ])
        .catch( / ... / );
    .catch( / ... /)

This is the function that runs when our service worker installs. First, we initialize and open a cache. This is a specific place where the files will be stored on the user's machine.

caches.open returns a promise with a reference to the cache we opens. Then we use addAll to pass in an array of strings. These are file paths, and they are added to the cache we created. Lastly we'll add a few catch functions for any error handling we need.

Next step is activate:

// serviceworker.js
self.onactivate = function(event) {
    console.log('sw is up and running!');

This can be a good place for clean up, but we'll save that for another blog post.

We saved the best for last! Let's take a look at fetch.

// serviceworker.js
self.onfetch = function(event) {
        .then(function(cachedFiles) {
            if(cachedFiles) {
                return cachedFiles;
            } else {
                return fetch(event.request);

This function will run when the service worker detects a fetch request. This function in all caches attempting to find a matching request. If a matching request is found, the function returns that request. Otherwise the service worker will go ahead and go over the network with the request.

Let's take a closer look at event.respondWith and caches.match, both of which are pretty service worker specific.

event.respondWith is a function which allows you to intercept a fetch request and give your own response instead. It's important to use this function instead of simply returning a response because this is what allows your intercepted response to be sent to the correct place.

caches.match is a function that allows us to search through CacheStorage and find a match for our request. When we add something to our cache, it'll be stored in a stack, with the oldest additions at the bottom and the newest at the top. caches.match will find the newest match and return that. If it doesn't find a match at all, it'll return null.

And that's it! That's everything you need for a simple starter service worker! If you think service workers are super cool, I'd recommend seeing what else they can do, including background fetch, in this blog post.

If you want to learn more about service workers, I hope you'll head over to serviceworkerbook.com and sign up for my mailing list, and follow me on Twitter! You'll be the first to know when my book, 'Let's Take This Offline' is out!

Carmen Bourlon

About Carmen Bourlon

Carmen is a software developer living and working in Oklahoma City, with a special interest in offline technology. She has spoken at multiple conferences about Offline First, and organizes a local women's technology group. In her spare time, Carmen defends Hyrule from the evil Ganon and writes Twitter-bots.

Recent Features

  • By
    Vibration API

    Many of the new APIs provided to us by browser vendors are more targeted toward the mobile user than the desktop user.  One of those simple APIs the Vibration API.  The Vibration API allows developers to direct the device, using JavaScript, to vibrate in...

  • By
    Introducing MooTools Templated

    One major problem with creating UI components with the MooTools JavaScript framework is that there isn't a great way of allowing customization of template and ease of node creation. As of today, there are two ways of creating: new Element Madness The first way to create UI-driven...

Incredible Demos

  • By
    Multiple File Upload Input

    More often than not, I find myself wanting to upload more than one file at a time.  Having to use multiple "file" INPUT elements is annoying, slow, and inefficient.  And if I hate them, I can't imagine how annoyed my users would be.  Luckily Safari, Chrome...

  • By
    Better Pull Quotes with MooTools

    Chris Coyier authored a post titled Better Pull Quotes: Don't Repeat Markup a while back. In his post he created great-looking pull quotes without repeating any content -- instead he uses jQuery to dynamically create the pull quotes. The following is the...


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