What is a Service Worker? Transform Your Web Site to an Instant Loading Powerhouse!

what-is-a-service-worker

A Service Worker is a script that executes in the background, in a separate thread from the browser. They enable deeper platform integration for the web, like rich caching, push notifications and background sync. Service workers are designed to be an extensible platform, additional features are currently being planned.

Service workers are have been called a game changer for the web. I don't think that is a simple exaggeration, because they enable many much needed capabilities and make the core architecture I have been using the past 7 years native.

Service Workers sound amazing!

How Do Service Workers Work?

A Service worker sits between the browser and the network, acting like a proxy server, handling a collection of non-UI centric tasks. They are event driven and live outside the browser process, enabling them to work without an active browser session. The service worker is a script that executes in a thread, separate from the UI. This enables the service worker to perform non-UI tasks, making a web site perform better.

service-worker-proxy

The first power a service worker brings to a web site is the ability to enable offline capabilities with granular control. This is done with a rich caching API and intercepting all network requests before they leave.

Caching not only enables offline experiences, websites can load instantly when retrieved from cache. Service worker caching makes the network a progressive enhancement, or not required to make the site usable.

Service Worker Extensibility

An underestimated service worker feature is its extensibility Service workers are designed to be the backbone that supports additional functionality. The first two features shipping in browsers are native push notifications and background sync. More new APIs are currently being debated and should start appearing in browsers in the near future.

Service workers live in their own thread and do not have access to the DOM. They also have their own global scope, referred to using the 'self' object.

The also require a site is served using HTTPS. This requirement is due to the powerful features service workers offer. HTTPS prevents many common attacks. Today all sites should be served using HTTPS as the barriers to implement have been lifted and the minimal amount of security they offer.

They are also asynchronous. This means all APIs support promises. This also means certain APIs and functions are not accessible in service workers. The most notable is localStorage. Instead, data should be stored using IndexedDB.

Before diving into these great service worker features developers need to understand the life cycle.

Service Worker Life Cycle

sw-life-cycle-work-flow

A service worker must be registered by a website. Because some browsers still don't support service workers you should perform a feature check before registering a service worker. This is done by checking for the presence of serviceWorker in navigator.

  if ('serviceWorker' in navigator) {    navigator.serviceWorker.register('/sw.js').then(function(registration) { // Registration was successful  }).catch(function(err) { // registration failed :(  });   }  

To register the service worker call navigator.serviceWorker.register. Pass the path to the service worker. The register function returns a promise.

If successful the promise returns a reference to the service worker registration object. From there you can perform specific UI tasks as needed.

When a service worker is registered the 'install' event. In this event the most common task to perform is called pre-caching.

Pre-caching is where a pre-defined list of assets files needed to form a page or site, and add them to cache before they are requested. This takes advantage of the service worker cache to persist these responses.

self.addEventListener("install", event => {    event.waitUntil(    caches.open(preCacheName).then(function (cache) {    return cache.addAll(precache_urls);    }));    });  

The install event is only triggered once in a service worker's life time. The event will not trigger again until the service worker is updated.

The next event that fires as part of the registration life cycle is 'activate'. When a service worker is installed it does not immediately become active. The natural sequence is for a new service worker to wait until all service worker 'clients' are closed.

The reason service workers are designed not to immediately take over is to keep them from breaking the user experience.

The skipWaiting function forces a waiting service worker to become active. This should only be employed when you are certain the new service worker will not break any existing clients.

self.skipWaiting();  
sw-life-cycle-diagram

Once the service worker becomes active the 'activate' event fires.

self.addEventListener("activate", event => {    //on activate  event.waitUntil(clients.claim());    });  

This event is commonly used to perform any clean up or migration tasks. For example, removing legacy caches that might conflict with the new service worker caches.

Service Worker Caching

The service worker specification includes native caching capabilities. This replaces the traditional appCache that has caused many management issues since it was created. Service worker caching is much more manageable.

The cache API provides a persistence layer that stores network responses which can be queried by the matching request.

The key to using service worker caching is the service worker 'fetch' event. This event triggers for each network request allowing you to intercept the request and check if the response has been cached before it goes to the network.

By accessing assets in local cache you can forgo expensive network requests. This means the site can work when there is no network, offline, or poor network connectivity, low bars or false cellular connectivity (known as LiFi).

self.addEventListener("fetch", event => {    event.respondWith(    fetchFromCache(event)  .catch(() => fetch(request)  .then(response => addToCache(cacheKey, request, response))  .catch(() => offlineResponse(resourceType, opts))    )    );    });  

In the example above the code checks is a response has been previously cached. If so, the cached response is returned. If not the request is passed along to the network.

sw-caching-diagram

When the request returns the response is cached and returned to the UI.

If the network fails the logic falls back to an offline response.

Service workers your applications never felt so good from Chris Love

There are a lot of moving parts being used in the example code. I will provide more details in a follow up articles.

Progressive Web App Training and Examples

Still not sure how to upgrade your existing site to a progressive web app? No worries, feel free to contact Love2Dev. We would love to get your started and help you unlock the best way to engage with customers.

progressive web app (PWA) beginner to expert online course

Do you want a much more detailed set of progressive web app and service worker tutorials? I just launched a new course, Progressive Web Apps : From Beginner to Expert.

This course covers everything you need to know to make any website a progressive web application. There are beginner topics to help anyone get started with progressive web app and service worker development. There are also modules to teach you how to polyfil many modern PWA features like offline and add to homescreen tactics.

Enroll today and save $171 off the $200 price. Progressive Web Apps : From Beginner to Expert is only $29 for a limited time.

Summary

Service workers are still relatively new to the web and provide a new dimension of capabilities developers are just starting to learn. The service worker programming model is much different that traditional web programming.

Share This Article With Your Friends!