Precaching with Workbox

Precaching is one of the most common things you'll do in a service worker, and Workbox offers lots of flexibility in how you can accomplish this important task, regardless of which one of Workbox's build tools you choose. In this guide, you'll learn how to precache assets using both generateSW and injectManifest, as well as which of these methods might be the best fit for your project.

Precaching with generateSW

generateSW is the easiest way to precache assets in Workbox. The big thing to remember about generateSW is that you are not writing your own service worker—you're asking Workbox to generate one for you. However, you can influence its behavior through a variety of configuration options.

generateSW does different things by default depending on which build tool you use. When using workbox-webpack-plugin, you don't have to specify any configuration options. By default, the plugin will precache everything webpack includes in its dependency graph and write a service worker named service-worker.js to the directory specified by output.path

On the other hand, if you use workbox-build or workbox-cli, only HTML, CSS and JavaScript assets read from the local filesystem will be precached by default. Configuration-wise, you have to specify swDest and the globDirectory option in the generateSW config for precaching to work. Chances are, you'll want to configure additional options affecting your service worker behavior as well, so take a look through the documentation.

Precaching with injectManifest

Using injectManifest isn't as easy as using generateSW, but you're trading off ease of use for greater flexibility. Where generateSW handles the entire service worker generation for you, injectManifest takes a service worker you write as its source and injects a list of URLs to precache, while leaving the rest of your service worker as-is.

When you use injectManifest, you're responsible for wiring up precaching logic. When injectManifest examines your input service worker, it looks for a special self.__WB_MANIFEST variable and replaces it with the precache manifest. If this variable isn't present, injectManifest will throw an error.

The list of entries in the precache manifest can be tweaked with additional configuration options.

Side-by-side comparison

Click on each of the tabs below to compare the usage of the generateSW and injectManifest methods:

Since generateSW generates a service worker, you only need to specify a configuration. Below is an example using workbox-build:

// build-sw.js
import {generateSW} from 'workbox-build';

generateSW({
  swDest: './dist/sw.js',
  globDirectory: './dist',
  globPatterns: [
    '**/*.js',
    '**/*.css',
    '**/*.svg'
  ]
});

The service worker can then be built on the command line with Node:

node build-sw.js

Since injectManifest requires a source service worker, a minimally viable example requires a source service worker file. If all that's needed is precaching, that input service worker might look something like this:

import {precacheAndRoute} from 'workbox-precaching';

precacheAndRoute(self.__WB_MANIFEST);

Note the self.__WB_MANIFEST string. This is a placeholder that Workbox replaces with the precache manifest. Below is a valid configuration for this use case:

// build-sw.js
import {injectManifest} from 'workbox-build';

injectManifest({
  swSrc: './src/sw.js',
  swDest: './dist/sw.js',
  globDirectory: './dist',
  globPatterns: [
    '**/*.js',
    '**/*.css',
    '**/*.svg'
  ]
});

injectManifest is preferable if you have complex requirements, such as advanced routing, custom caching strategies, or other things that aren't covered by the options generateSW provides.

Conclusion

Precaching in Workbox is much simpler than if you had to manage precaching on your own, especially where versioned assets compiled by bundlers are concerned. However, precaching isn't the only thing you'll likely do in a service worker. As you proceed, you'll learn other techniques, such as runtime caching.