< More blog posts

Development

A Complete Guide to Service Workers

Trevor Brixey
April 30, 2019

Summary

I will be going over Service Workers at a very high level in this post. Later on, I will discuss how you could implement a service worker into your React application. At the bottom, there will be links to all my sources and documentation, so you can learn more!

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
  • JavaScript code that executes on page load.
  • Gives developers much more control of the browser.

Service Worker Lifecycle

no service worker graphic chart

Why should we use it?

  • Required for a Progressive Web App
  • Provide offline website support
  • Can make your site have a heartbeat by watching for site updates and even auto update! (This can include things like forcing a user to utilize a new build when pushed out, or just notifying them there is an update.)
  • If no offline support is needed, it speeds up site revisits by caching the site code.
  • Significantly lowers your deployment downtime.
  • Your users are running the site on their local copy and aren't relying on the server, even when clicking links and navigating around your site.

Website screenshot reference. We are serving some high sized images directly from our server.

picture of cat and buildings and map

Download size & load times without a service worker

Download size & load times with a service worker

As you can see, there is a huge difference in load times and bandwidth utilization! We only have to download the images once when the service worker is utilized vs every page load when it doesn't exist. Of course, you could throw the images on a separate image hosting platform like the one I'm using for the images above, but that might be against security standards for your app. Also, images aren't a great example, but imagine your application is very large scale and you have a lot of code that needs to be served up. Your browser won't be able to auto-cache that, and you can't access it offline.

Think about mobile!

The image below is from a tomsguide article that talks about mobile network speeds.

tom's guide to the fastest wireless network chart

Sure those seem pretty quick, but these are best case scenarios. The article goes on to talk about this as they only tested "...wireless network speeds at multiple locations in eight U.S. cities in the past year...". With service workers your users will be able to revisit your application much faster even while using slower internet speeds.

in addition to mobile...

Have you ever been in a coffee shop to spin up your favorite website and it took forever? It could be possible that your favorite site isn't implementing any sort of caching. Because of this, while you are sipping your favorite drink, you can't browse the site you wanted to browse! Unfortunately, you probably won't be able to get ahold of their dev team and show them this article.

You were probably on your laptop at that coffee shop, which should be faster than your phone, right? Well... not necessarily. Most coffee shops have lower tier data plans, and it shares with everyone in the building (even employees and shop devices).

Here is a graph by speedtest.net that shows global internet speeds. This really shows that you have to think about network speed and users coming back to your application. You don't want everyone taking 3 seconds to load your page every time (maybe longer, maybe shorter).

fixed internet average speed chart

I'm in! How do I get started?

If you are using React, then this is going to be a piece of cake! If you aren't using React, I recommend heading here to learn more about how you can register your own service worker.

My recommendation is to utilize the package offline-plugin due to the versatility and options it provides. You could totally use the one that comes with Create-React-App(CRA) if you wanted to, but you will miss out on a lot of functionality. What's built into CRA is a good start for sure, especially if you aren't interested in any of the options offline-plugin provides.

Basic service worker implementation via CRA.

This snippet is located in your src/index.js file by default!

_______________________________________________________________

import * as serviceWorker from "./serviceWorker";

// ...

serviceWorker.register();

_______________________________________________________________


offline-plugin implementation

You've made it this far, so I'm going to make it nice and easy for you. Follow these steps if you are wanting a service worker with auto updating functionality.

  1. npm i offline-plugin react-app-rewired --save-dev in your project directory.
  2. Go to your projects root directory (where your package.json is located) and create a new file called config-overrides.js.
  3. In that file paste the following:

_______________________________________________________________

// This is a good baseline for setting up auto install
const OfflinePlugin = require("offline-plugin");

module.exports = function override(config, env) {
 if (!config.plugins) {
   config.plugins = [];
 }
 config.plugins.push(
   new OfflinePlugin({
     autoUpdate: true, // true = check every hour for an update while user is connected to your application.
     ServiceWorker: {
       events: true
     }
   })
 );
 return config;
};

_______________________________________________________________


  1. From here you have to decide if you want to alert or enforce the user to update when you push a new verion. If yes... continue! If no then you are done! 🎉
  2. Let's give the user an option to update! In a new component that gets mounted on site visit let's add some code!

_______________________________________________________________

import React, { Component } from "react";
import runtime from "offline-plugin/runtime";

class Updater extends Component {
 state = {
   updateSite: false,
   updating: false
 };

 componentDidMount() {
   // You can test on local development my remove or changing this if
   if (process.env.NODE_ENV === "production") {
     runtime.install({
       onUpdateReady: () => {
         this.setState({ updateSite: true });
       }
     });
   }
 }

 applySomeUpdate = () => {
   runtime.applyUpdate();
   setTimeout(() => {
     window.location.reload(true);
   }, 1000); // Give some time for the new service worker to start after the update
 };

 render() {
   return (
<div>
       {this.state.updateSite ? (
<button onClick={this.applySomeUpdate}>Update now!</button>
       ) : null}
</div>
   );
 }
}

export default Updater;

_______________________________________________________________


  1. Boom! 💥 Well kind of... You should definitly style this and make it your own!

You now have a very rough example of a component that will show a button when a new service worker is ready to be installed. This will run every time someone visits your site. The best part is that a check for a new service worker costs nothing! 0 bytes and 0 lag!

You've made it to the end, and hopefully with a better understanding of service workers and why they are so great. I (and now you) have barely grazed the surface of service workers. With the limited understanding we both have, we can all push for a better web. Making our applications faster and more accessible together.

Now get out there and hire some Service Workers!

Thank you! 🙏

References

service-worker docs

mobile network speed

speedtest

service-worker registration

Create-React-App

offline-plugin

react-app-rewired