Role of Service Worker In PWAs
Tags: pwa, beginners, webdev, javascript
Published: 2023-06-18 18:07:44

Hello Folks!! In the previous article, we learnt about [service workers](https://dev.to/anuradha9712/service-workers-4h58) and their lifecycles. In this article let's see service workers in practice.

![lifecycle](https://cdn.hashnode.com/res/hashnode/image/upload/v1687025991673/b2acaa3a-2ff8-422f-a2d7-0f8fdd74afc7.png)

## **🎯** Register a Service Worker

Create a service worker and register it in a browser from another javascript file.

In file `js/app.js`:

```javascript
// Step 1: register a service worker
if('serviceWorker' in navigator){
  navigator.serviceWorker.register('/sw.js')
  .then((reg) => console.log('Service Worker Registered', reg))
  .catch((err) => console.log('Error in Registering Service Worker', err))
}
```

* First, we will check if the browser supports the service worker or not.
    
* `navigator` is an object in javascript that represents the browser and information about it.
    
* In `register` method we need to provide the path to our service worker file.
    

Now you can check the result in the browser.

![register-event](https://cdn.hashnode.com/res/hashnode/image/upload/v1685813347618/5dc045b4-e55e-41e6-91e4-ec409fe06361.png)

![register-event-1](https://cdn.hashnode.com/res/hashnode/image/upload/v1685813525795/870ca21a-bf03-4b6d-8731-572acb9b9c0d.png)

**Points to remember:**

* Service workers only work on pages where they're served over a secure HTTPS connection. Also, localhost is an exception so that we can easily develop an app using service workers.
    

## **🎯** Install Event

The browser emits the install event automatically while the service worker is being installed. So we can listen to that install event.

Create a new file `sw.js` in the root directory so that it has access to the overall scope.

In file `sw.js`:

```javascript
const staticCacheName = "site-static-v2";
const assets = [
  "/",
  "/index.html",
  "/js/app.js",
  "/css/styles.css",
  "https://unpkg.com/@innovaccer/design-system@2.15.3/css/dist/index.css",
  "https://fonts.googleapis.com/css?family=Nunito+Sans:300,300i,400,400i,600,600i,700,700i,800,800i,900,900i&display=swap",
  "https://fonts.gstatic.com/s/nunitosans/v12/pe03MImSLYBIv1o4X1M8cc8GBs5tU1ECVZl_.woff2",
  "/pages/404.html"
];

// Step 2: Install Service Worker
self.addEventListener("install", (event) => {
  console.log("service worker has been installed!!");
  event.waitUntil(
    caches.open(staticCacheName).then((cache) => {
      console.log("caching shell assets");
      cache.addAll(assets);
    })
  );
});
```

* `self` inside a service worker refers to the service worker itself.
    
* This event will occur only when we first install it or any changes in the file have been made.
    
* We can use this event to add common assets to the cache so that users can still see those assets in the offline mode.
    

![install-event](https://cdn.hashnode.com/res/hashnode/image/upload/v1685815529787/ca6f2146-4151-418b-942e-003ff17f4f6e.png)

## **🎯** Activate Event

When the service worker is installed it becomes active. Once the service worker is active, it can access all the different pages and all the different files **inside its scope.**

```javascript
const clearOldCaches = () =>
  caches.keys().then((keys) =>
    Promise.all(
      keys
        .filter((key) => key !== staticCacheName && key !== dynamicCacheName)
        .map((key) => {
          console.log("[sw] remove cache", key);
          caches.delete(key);
          return true;
        })
    )
  );

// Step 3: Activate Service Worker
self.addEventListener("activate", (event) => {
  console.log("service worker has been activated!!");
  
  event.waitUntil(clearOldCaches());
});
```

![activate-event-1](https://cdn.hashnode.com/res/hashnode/image/upload/v1686507245679/d15a86ee-9c10-41af-8c9a-988c487b52b0.png)

The service worker will wait to activate until all the instances of the app will be closed.

![activate-event-2](https://cdn.hashnode.com/res/hashnode/image/upload/v1685820027118/3714c64c-98bd-48d4-b6dc-fbd218ec0e42.png)

But it is a bit tedious as we have to first close all the tabs on which our app is running and then it reinstalls and comes under the running state. To avoid this we can use the following approaches:

* use the `skipWaiting` option.
    
* use `Update on reload` option.
    

## **🎯** Fetch Event

The fetch event occurs whenever we try to get something from a server like any CSS file or javascript file.

We have `index.html` file running in the browser which was initially fetched from a server. When an app requests a stylesheet or images or some other page it sends a request from the browser to the server and in response gets the requested resources.

We also have a service worker in the background listening for any fetch requests from our app. This service worker **acts as a proxy** between our app and a server.

Now whenever we make any request for resources it goes through the service worker and at this point, a fetch event is emitted and the service worker can listen for and react to it. We can either intercept the request or sent a custom response.

Service workers **handle the cached asset** and while making a fetch request we can prevent to sent the request directly to the server and instead send cached resources.

![fetch-request](https://cdn.hashnode.com/res/hashnode/image/upload/v1686505981711/26204719-57ea-440a-b085-5f7b6794a7c2.png)

```javascript
self.addEventListener("fetch", (e) => {
  e.respondWith(
    (async () => {
      const r = await caches.match(e.request);
      console.log(`[Service Worker] Fetching resource: ${e.request.url}`);
      if (r) {
        return r;
      }
      const response = await fetch(e.request);
      const cache = await caches.open(dynamicCacheName);
      console.log(`[Service Worker] Caching new resource: ${e.request.url}`);
      cache.put(e.request, response.clone());
      return response;
    })()
  );
});
```

![fetch-request-1](https://cdn.hashnode.com/res/hashnode/image/upload/v1686507336368/cf807e17-ef5f-4896-bc0e-adbe6231e74c.png)

Now we have seen all the lifecycle events of the service worker. A service worker is one of the steps in creating a Progressive web app. Let's see how to audit your application.

## **🎯** Lighthouse Audit

Chrome dev tools give us a way to audit our application using the lighthouse plugin which provides us with a checklist of required actions to make a site a valid PWA.

Go to the `Lighthouse` tab in Chrome dev tools and check the Progressive Web App option and press the **Analyze page load** button.

![lighthouse-audit](https://cdn.hashnode.com/res/hashnode/image/upload/v1686708863966/5476e9c7-19ce-4036-b95e-d86f0b1a047f.png)

![result](https://cdn.hashnode.com/res/hashnode/image/upload/v1686709031454/23194eaa-e09c-4545-99c7-640dbd84e425.png)

It provides us with the checklists to complete to create a valid PWA.

## **🎯 Install Prompt**

We can also get an 'Install Banner' in our app by fulfilling certain criteria. This banner is similar to **Add to home screen** option which allows us to install the application into our device.

![install-prompt](https://cdn.hashnode.com/res/hashnode/image/upload/v1686709780989/ee3d7e1d-609f-4955-8a36-ff429c72fb6e.png)

![result](https://cdn.hashnode.com/res/hashnode/image/upload/v1686709894702/aef6e424-5f2b-47df-a58a-4ef417a09df0.png)

We can check all the criteria to show the install banner on this [site](https://developer.chrome.com/blog/app-install-banners-native/).

## **🎯 Wrap Up!!**

That's all for this article. Thank you for your time!! Let's connect to learn and grow together. [**LinkedIn**](https://www.linkedin.com/in/anuradha-aggarwal-4a2751107/) [**Twitter**](https://twitter.com/Anuradh06359394) [**Instagram**](https://www.instagram.com/blogcode404/)

[![Buy-me-a-coffee](https://cdn.buymeacoffee.com/buttons/v2/default-blue.png)](https://www.buymeacoffee.com/anuradha2612)