JS Service Workers — An Introduction
Tags: javascript, progressivewebapp, serviceworkers, webdev
Published: 2020-12-23 09:03:43

## JS Service Workers — An Introduction

#### A journey towards taking your web application offline

## The Why

You have created an awesome website and ready to host it for everyone to find. You have taken the pain of making it responsive and it looks great on all standard devices. Let us walk through a hypothetical Developer vs Product Manager conversation:

> **_PM:_** Is this application responsive?
> 
> **_Dev:_** Yes boss!
> 
> **_PM:_** Does it work when he is on a slow internet?
> 
> **_Dev:_** Well, I have minimized the assets, serving them up gzipped, so its optimised, but might take a while to load.
> 
> **_PM:_** What if he goes offline?
> 
> **_Dev:_** (Dumbfounded)Web… Web application? Why would someone use a web application offline? We need to create apps if we want to provide offline capabilities!

The next part of the conversation might not be very pleasant, so let us skip that. **_What if I told you your web app can be taken offline? What if I told you that your app can act like a native application in multiple platforms and be pinned to the Start screen for easy access?_** Welcome to PWA, welcome to the future (not really, it has been around for a while. While [Google introduced PWA](https://youtu.be/MyQ8mtR9WxI) in 2015, [Steve Jobs conceptualized it](https://youtu.be/ZlE7dzoD6GA) back in 2007!)

## What does it take?

One word: _JavaScript_

If you are a front end developer, you are already aware of JS, and its nitty-gritty details. You don’t have to learn Java, you don’t have to download software to develop an android app, and yet another for iOS. You don’t have to take the trouble of publishing it across multiple stores. You simply build upon your already existing awesome webpage.

## Google Lighthouse
![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1606673088647/8Gdysjj8S.png)

Have you seen the _lighthouse_ tab (it would come as an _audit_ on older versions) on Chrome developer tools? Go to any site and run it. You see a couple of metrics — how well does the site perform, does it take into account accessibility, does it follow best practices, and finally **does it have what it takes to be a PWA**? This report then has details on how to improve upon the site and is a great place to start enhancing your application.

## What is a Service Worker

> A service worker is a script that your browser runs in the background, separate from a web page, opening the door to features that don’t need a web page or user interaction. — [Matt Gaunt](https://developers.google.com/web/resources/contributors/mattgaunt) on [Web Fundamentals](https://developers.google.com/web/fundamentals)


![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1606737952102/sk9mstkLl.png)
*Service Worker Overview from [Introduction to Service Workers](https://docs.google.com/presentation/d/1bFVDRa71JK0ilr6lS6y9Twqp9gy8jzV1O8FFbG4A3qk/edit#slide=id.p9) by Google*

Let us now dissect the definition:

_A service worker is a script_ — It is composed of **JavaScript.** Also note, it is a worker and hence cannot access DOM elements [No more _alert(“hello!”)_], but has to communicate using messages.

_Runs in the background —_ It is run on a **different thread** than the main JS even loop. Note that it might be terminated when not in use, and restarted when required, hence using global variables is a very bad idea.

_Opening the door to features —_ It is a programmable network proxy and can intercept requests, respond on behalf of server and cache resources.

_Don’t need a web page or user interaction —_ Push notifications, background sync, payment updates — service works bring a lot of handy features to the web platform.

## Service Worker Life Cycle

The lifecycle of a service worker is not coupled with the web page. It starts with the first load of the page but persists long after the browser tab is closed.

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1606738002464/6jy7oByZ-.png)
*Service Worker Life Cycle by [Matt Gaunt](https://developers.google.com/web/resources/contributors/mattgaunt) on [Web Fundamentals](https://developers.google.com/web/fundamentals)*

The first step of registering a service worker is the install step. _Typically, assets are downloaded and cached in this step_. If all goes well, it moves to the activated step, else moves to the error state. Once activated, it is ready to intercept requests and process messages. _Typically, old caches are invalidated here_. When there is no activity, it remains idle, and after a few seconds of idling, is terminated. No need to be alarmed, it is brought back to life when a new event occurs, like a request or message. Note that since the worker can be terminated at any point, using global variables is heavily discouraged. IndexedDB can be used to persist data, including cache. The service worker is terminated after some seconds of inactivity to ensure that they don’t live in memory, draining resources.

Service workers are extensively asynchronous and use Promises. No blocking actions are allowed in the worker, failing which it will be stopped.

## Can I use Service Workers?

Web developers have lost a lot of their hairs owing to browsers deviating from web standards, it is only natural to have this question at the back of your head while reading through this article. The short answer is no. While some do not support it all together, some allow limited features. The amount of storage also varies from platform to platform and from browser to browser.


![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1606738020731/p9GEWXoYS.png)
*Browser compatibility of Service Worker, screenshot from [caniuse.com](https://caniuse.com/?search=serviceworker)*

Hence it is a good practice to do a feature test before installing a service worker. We should not have core functionalities in service workers as it might be executed in an incompatible platform-browser combination.

Another factor to keep in mind is that Service Workers can be used only on **HTTPS**-enabled websites. While it works on HTTP through _localhost_, it will not work in an insecure site. Service workers are powerful, and “_with great power, comes great responsibility_”. HTTPS ensures that the source of the script is the hosted site and protects against man-in-the-middle attacks.

## Time to Code

Time to whip up some throwaway code! We will start with a simple HTML file with some script. We have a div with an id that we will change. We first check if we can rester a service worker, and if we can, go ahead to register it. Once it is registered, the DOM is updated. We also have logging of errors and meaningful messages to the DOM if something fails.

*index.html*
```html
<!doctype html>
<title>First Service Worker</title>

<h1>Service Worker Test</h1>
<div id="response"></div>

<script>
// chcek if the browser supports service workers
if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register("serviceworker.js",
        { scope: "/" })
        .then( registration => {
            // registration is an handle of the worker.
            // More event listeners can be attached or messages can be sent to this.
            // For this example, we just change the DOM to display message
            document.getElementById("response").innerHTML = 
                "Service Worker registered properly";
        })
        .catch( error => {
            // Update DOM and log error in case resgistration fails
            document.getElementById("response").innerHTML = 
                "Service Worker NOT registered";
            console.error(error);
        });
} else {
    // UPdate DOM to reflect service workers cannot be used
    document.getElementById("response").innerHTML = 
                "Service Worker NOT available";
}
</script>
``` 

*serviceworker.js*
```js
console.log("We are a service worker");

// This is called once the worker is installed
self.addEventListener("install", event => {
   console.log("Install event");
});

// This is called once the worker becomes active
self.addEventListener("activate", event => {
   console.log("Activate event");
});
```

The _serviceworker.js_ file is a barebone for now. We have logs to illustrate the flow. First, it is installed and then activated.

Let me walk you through on how to run this. You can get both the files from the above _gist_, but if you open the file in a browser it will not work. You’ll need to serve up the contents. The easiest way is to use the npm package called “_serve”_ (assuming you have [NodeJS](https://nodejs.org/en/download/) development environment setup). You can navigate to the folder where you have these files and execute the following:


```bash
npm i -g serve
serve
```

This will start serving the contents of the folder at port 5000\. If you click on the link [http://localhost:5000](http://localhost:5000) you’ll see the service worker is registered properly. If you click the network link (the one below local), the service worker will not work (remember HTTPS). In the debugger, you can see the details, as shown below, in the application tab. When you are developing, ensure that “Update on reload” is checked so that changes that you make to your worker are picked up. By default, a service worker once installed will always remain installed (but more on this later).


![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1606738827384/m9mnqO8O9.png)
*Chrome Debug tool to inspect service worker*

## Coming up

This is the first of the series. More on service workers would be posted in the coming weeks. In the meantime, this piece sites a lot of resources that you can explore. Stay tuned to keep learning!

---
Originally published at [https://medium.com/ones-zeros/js-service-workers-an-introduction-12aabeea1a2b](https://medium.com/ones-zeros/js-service-workers-an-introduction-12aabeea1a2b)

<a href="https://www.buymeacoffee.com/royniladri" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-blue.png" alt="Buy Me A Coffee" width="170"></a>