JavaScript Service Worker Basics

An Object Is A
3 min readSep 18, 2020

The basis for Progressive Web Apps

Service workers provide a way to increase the persistence functionality of your web pages.
They create a layer between your fetch calls for resources — from local or remote servers — and the eventual receiving of those resources.
In this layer, you can write code to cache or use cached files before actually responding to fetch calls.

Service workers go through a life cycle:
1. Registration
2. Installation
3. Activation

We’ll take a look at these and what we can do in them.

Registration.

To register a service worker we use the ‘register’ method in the ‘serviceWorker’ object.

register’ takes two arguments:
- the location of the service worker (a .js file)
- the scope (which directories the service worker has the power to influence; the directory and sub-directories OF the service worker are valid)

/* script.js */let registration = null;function register_service_worker() {
if ('serviceWorker' in navigator) {
window.navigator.serviceWorker.register('./sw.js',
{ scope: './' })
.then(res => {
registration = res;
console.log("SW successfully registered.");
})
.catch(err => {
console.log("Could not register service worker.");
});
}
}

We also have ability to “unregister” our service worker.

/* script.js */function unregister_service_worker() {
navigator.serviceWorker.getRegistrations()
.then(registrations => {
registrations.forEach(registration => {
registration.unregister();
console.log("Service Worker ungregistered.");
})
})
.catch(err => {
console.log("Could not unregister service worker.");
});
}

Installation.

After the ‘service worker’ successfully registers, an ‘install’ event will fire.
We can listen for this.

It’s here where we setup our page for, most commonly, offline use.

Just like when you download a program onto your computer, running that executable unpacks, copies, and saves files from that executable to your hard-drive.

You’re installing the program…

We do the same with a service worker.
We have to create that executable.
We have to specify which files need to be included in the install.

We can use the ‘cache’ API or the ‘IndexedDB’ API for this.
We’ll use the ‘cache’ API.

To tell the ‘service worker’ which files to include in the installation, we use ‘event.waitUntil()’ which takes a promise.
We can use ‘cache.open()’ which returns a promise.

Once we successfully open a cache, we can specify files to save using ‘cache.add()’ or ‘cache.addAll()’.

The ‘cache’ API saves files in key:value pairs just like a JavaScript object.

The keys are ‘REQUEST’ objects.
The values are ‘RESPONSE’ objects from those requests.

The ‘request’ objects are the same as if you used an HTTP request object.
The ‘response’ objects are the same HTTP response objects you get back.

/* sw.js */self.addEventListener('install', event => {
self.skipWaiting();
event.waitUntil(
caches.open('v1')
.then(cache => {
cache.addAll([
'./', // the index.html
'./script.js', // the main script
'./obj.png' // local img; same dir as script.js
]);
console.log("Assets cached.");
})
.catch(err => console.log("Could not cache."))
)
});

Using a Service Worker.

To actually use this ‘service worker’ we just listen for ‘fetch’ calls;
The exact same fetch calls you can make manually in JavaScript using the fetch API.

This is what a ‘service worker’ does.

It acts like a proxy server; something between your page and the ACTUAL server you’re trying to ping.

We can intercept this call and do anything we want with it.

Note:
For good coding practices you should always return some sort of promise to an ‘event.respondWith()’.
That promise should always resolve into something otherwise you’ll get an ‘undefined’ response for the fetch call.
If you don’t code for this, you’re code will fail.

Activation.

It’s in the ‘activate’ listener that you’ll clean up old cache files and generally do work you needed to remove old service workers.

/* sw.js */self.addEventListener('activate', event => {
event.waitUntil(
caches.keys()
.then(keys => {
keys.forEach(key => {
if (key === 'v1') caches.delete(key);
});
})
);
});

Service workers can be very confusing to read about and grasp.

If you would like a more in-depth guide, check out my full video tutorial on YouTube, An Object Is A.

--

--