Join us for web.dev LIVE, a digital event from June 30th to July 2nd to learn modern web techniques. More at web.dev/live

Get Started

This guide will show you how to get up and running with Workbox to route common requests for a web page and demonstrate how to cache using a common strategy.

Since most websites contain CSS, JavaScript and images, let’s look at how we can cache and serve these files using a service worker and Workbox.

Create and Register a Service Worker File

Before we can use Workbox, we need to create a service worker file and register it from our web page.

Start by creating a file called service-worker.js at the root of your site and add a console message to the file (this is so we can see it load).

console.log('Hello from service-worker.js');

In your web page, register your new service worker file like so:

<script>
// Check that service workers are supported
if ('serviceWorker' in navigator) {
  // Use the window load event to keep the page load performant
  window.addEventListener('load', () => {
    navigator.serviceWorker.register('/service-worker.js');
  });
}
</script>

This tells the browser this is the service worker to use for the site.

If you refresh your page, you'll see the log from your service worker file.

Console message from sw.js in DevTools

Looking in the “Application” tab in Chrome DevTools, you should see your service worker registered.

Application Tab displaying a registered service worker.

Now that we have a service worker registered, let’s look at how we can use Workbox.

Importing Workbox

There two ways to import Workbox into your service worker:

  • Using the workbox-sw loader, which loads Workbox packages at runtime from our CDN.
  • Using a bundler to include Workbox pages in your service worker at build time.

For quick experimentation and prototyping, loading Workbox from the CDN is usually easiest. On the other hand, bundling your service worker is generally recommended for more control and better integrations with existing tooling (for example, editor integration or writing your service worker in TypeScript).

From the CDN

To load Workbox from our CDN, update your service worker file to import the workbox-sw.js file via the importScripts() method.

importScripts('https://storage.googleapis.com/workbox-cdn/releases/5.1.2/workbox-sw.js');

if (workbox) {
  console.log(`Yay! Workbox is loaded 🎉`);
} else {
  console.log(`Boo! Workbox didn't load 😬`);
}

With this you should see the “Yay” message, which indicates that Workbox has loaded successfully.

DevTools screenshot of Workbox loading in a service worker.

Now we can start using Workbox.

Using a bundler

When loading Workbox from our CDN using the workbox-sw loader, a global workbox object is created, and each of the individual Workbox packages can be accessed via a property on the workbox global (e.g. workbox.precaching, workbox.routing, or workbox.backgroundSync).

When using a bundler to create your service worker, you install the Workbox packages you want to use from npm, and then you use import statements to directly reference the Workbox modules you want to use. In this scenario there is no global workbox object. Instead, your bundler will inline your imported Workbox modules directly into the service worker file it generates. For example:

import {precaching} from 'workbox-precaching';
import {registerRoute} from 'workbox-routing';
import {BackgroundSyncPlugin} from 'workbox-background-sync';

// Use the above modules somehow...

For more details see Using Bundlers (webpack/Rollup) with Workbox.

Alternatively, if you're using webpack you can use the workbox-webpack-plugin which handles bundling your service worker for you.

Using Workbox

One of Workbox’s primary features is it’s routing and caching strategy modules. It allows you to listen for requests from your web page and determine if and how that request should be cached and responded to.

Let’s add a cache fallback to our JavaScript files. The easiest way to do this is to register a route with Workbox that will match any requests that have a destination property set to 'script'.

import {registerRoute} from 'workbox-routing';

registerRoute(
  ({request}) => request.destination === 'script',
  /* ... */
);

The above code tells Workbox that when a request is made, it should see if the function returns a "truthy" value, and if it does, do something with that request. For this guide, that “do something” is going to be passing the request through one of Workbox’s caching strategies.

If we want our JavaScript files to come from the network whenever possible, but fallback to the cached version if the network fails, we can use the “network first” strategy to achieve this.

import {registerRoute} from 'workbox-routing';
import {NetworkFirst} from 'workbox-strategies';

registerRoute(
  ({request}) => request.destination === 'script',
  new NetworkFirst()
);

Add this code to your service worker and refresh the page. If your web page has JavaScript files in it, you should see some logs similar to this:

Example console logs from routing a JavaScript file.

Workbox has routed the request for any script resources and used the network first strategy to determine how to respond to the request. You can look in the caches of DevTools to check that the request has actually been cached.

Example of a JavaScript file being cached.

Workbox provides a few caching strategies that you can use. For example, your CSS could be served from the cache first and updated in the background or your images could be cached and used until they're a week old, after which they’ll need updating.

import {registerRoute} from 'workbox-routing';
import {CacheFirst, StaleWhileRevalidate} from 'workbox-strategies';
import {ExpirationPlugin} from 'workbox-expiration';

registerRoute(
  // Cache style resources, i.e. CSS files.
  ({request}) => request.destination === 'style',
  // Use cache but update in the background.
  new StaleWhileRevalidate({
    // Use a custom cache name.
    cacheName: 'css-cache',
  })
);

registerRoute(
  // Cache image files.
  ({request}) => request.destination === 'image',
  // Use the cache if it's available.
  new CacheFirst({
    // Use a custom cache name.
    cacheName: 'image-cache',
    plugins: [
      new ExpirationPlugin({
        // Cache only 20 images.
        maxEntries: 20,
        // Cache for a maximum of a week.
        maxAgeSeconds: 7 * 24 * 60 * 60,
      })
    ],
  })
);

What Else Can Workbox Do?

Routing and caching strategies are performed by the routing and strategies modules, but there are plenty of other modules, each offering specific behaviors that you can use in your service worker.

You'll find a number of guides that cover other features of Workbox as well as more information on configuring Workbox. Find a full list on the left, but the next natural step is to enable precaching, which is the process of adding files to the cache when your service worker loads.

Learn More About Precaching