Migrate from Workbox v3 to v4

This guide is focused on breaking changes introduced in Workbox v4, with examples of what changes you'd need to make when upgrading from Workbox v3.

Breaking Changes


The naming convention for precached entries has been updated. Now, for entries whose URLs need revisioning information (i.e. those entries that contain a revision field in the precache manifest), that versioning information will be stored as part of the cache key, in a special __WB_REVISION__ URL query parameter appended to the original URL. (Previously, this information was stored separate from the cache keys, using IndexedDB.)

Developers who take advantage of precaching via workbox.precaching.precacheAndRoute(), which is the most common use case, do not need to make any changes to their service worker configuration; upon upgrading to Workbox v4, your users' cached assets will automatically migrate to the new cache key format, and moving forward, precached resources will continue to be served in the same manner as before.

Using Cache Keys Directly

Some developers might need to access precache entries directly, outside of the context of workbox.precaching.precacheAndRoute(). For instance, you might precache an image that you end up using as a "fallback" response when an actual image can't be fetched from the network.

If you make use of precached assets this way, starting in Workbox v4, you'll need to take an additional step in order to translate an original URL into the corresponding cache key that can be used to read the cached entry. You do this by calling workbox.precaching.getCacheKeyForURL(originURL).

For example, if you know that 'fallback.png' is precached:

const imageFallbackCacheKey =

workbox.routing.setCatchHandler(({event}) => {
  switch (event.request.destination) {
    case 'image':
      return caches.match(imageFallbackCacheKey);
    // ...other fallback logic goes here...

Cleaning Up Old Precached Data

The changes made to precaching in Workbox v4 mean that older precaches, created by previous versions of Workbox, are not compatible. By default, they're left as-is, and if you upgrade from Workbox v3 to Workbox v4, you'll end up with two copies of all your precached resources.

To avoid this, you can add call to workbox.precaching.cleanupOutdatedCaches() to a service workers directly, or set the new cleanupOutdatedCaches: true option if using a build tool in GenerateSW mode. Because the cache cleanup logic operates on cache naming conventions to find older precaches, and because developers do have the option of overriding those conventions, we erred on the side of safety and did not enable this by default.

We encourage developers who run into any issues using this—such as false-positives around deletion—to let us know.

Parameter Capitalization

Two optional parameters that can be passed to workbox.precaching.precacheAndRoute() and workbox.precaching.addRoute() have been renamed, to standardize our overall capitalization convention. ignoreUrlParametersMatching is now ignoreURLParametersMatching, and cleanUrls is now cleanURLs.


There are two, roughly equivalent ways of creating an instance of a handler in workbox-strategies. We're deprecating the factory method, in favor of explicitly calling the strategy's constructor.

// This factory method syntax has been deprecated:
const networkFirstStrategy = workbox.strategies.networkFirst({...});

// Instead, use the constructor directly:
// (Note that the class name is Uppercase.)
const networkFirstStrategy = new workbox.strategies.NetworkFirst({...});

While the factory method syntax will continue working in v4, using it will log a warning, and we encourage developers to migrate in advance of removing support in the future v5 release.


The workbox.backgroundSync.Queue class has been rewritten to offer developers more flexibility and control over how requests are added to the queue and replayed.

In v3, the Queue class had a single way to add requests to the queue (the addRequest() method), but it did not have any way to modify the queue or remove requests.

In v4, the addRequests() method has been removed, and the following array-like methods have been added:

  • pushRequest()
  • popRequest()
  • shiftRequest()
  • unshiftRequest()

In v3, the Queue class also accepted several callbacks that allowed you to observe when requests were being replayed (requestWillEnqueue, requestWillReplay, queueDidReplay), but most developers found that, in addition to observation, they wanted control over how the queue was replayed, including the ability to dynamically modify, re-order, or even cancel individual requests.

In v4, these callbacks have been removed in favor of a single onSync callback, which is invoked any time a replay attempt is being made by the browser. By default the onSync callback will invoke replayRequests(), but if you need more control over the replay process, you can use the array-like methods listed above to replay the queue however you like.

Here's an example of custom replay logic:

const queue = new workbox.backgroundSync.Queue('my-queue-name', {
  onSync: async ({queue}) => {
    let entry;
    while ((entry = await this.shiftRequest())) {
      try {
        await fetch(entry.request);
      } catch (error) {
        console.error('Replay failed for request', entry.request, error);
        await this.unshiftRequest(entry);
    console.log('Replay complete!');

Similarly, the workbox.backgroundSync.Plugin class accepts the same arguments as the Queue class (since it creates a Queue instance internally), so it has changed in the same way.


The npm package has been renamed workbox-expiration, matching the naming convention used for other modules. This package is functionally equivalent to the older workbox-cache-expiration package, which is now deprecated.


The npm package has been renamed workbox-broadcast-update, matching the naming convention used for other modules. This package is functionally equivalent to the older workbox-broadcast-cache-update package, which is now deprecated.


In Workbox v3 the verbosity of log levels could be controlled via the workbox.core.setLogLevel() method, which you'd pass one of the values in the workbox.core.LOG_LEVELS enum. You could also read the current log level via workbox.core.logLevel.

In Workbox v4, all of these have been removed since all modern developer tools now ship with rich log filtering capabilities (see filtering the console output for Chrome Dev Tools).


Two methods that were previously exposed directly on the workbox namespace (which corresponds to the workbox-sw module) have been moved to workbox.core instead. workbox.skipWaiting() has become workbox.core.skipWaiting() and similarly, workbox.clientsClaim() has become workbox.core.clientsClaim().

Build Tool Configuration

The naming of some options that can be passed in to either workbox-cli, workbox-build, or workbox-webpack-plugin has changed. Whenever "Url" was used in an option name, it's been deprecated in favor of "URL". This means that the following option names are preferred:

  • dontCacheBustURLsMatching
  • ignoreURLParametersMatching
  • modifyURLPrefix
  • templatedURLs

The "Url" variation of those option names still works in v4, but will result in a warning message. We encourage developers to migrate in advance of the v5 release.

New Functionality


The new workbox-window module simplifies the process of service worker registration and detecting updates, and provides a standard means of communication between code running in the service worker and code running in your web app's window context.

While using workbox-window is optional, we hope that developers will find it useful, and consider migrating some of their handwritten logic to use it when appropriate. You can learn more about using workbox-window in the module's guide.

Example Migration

An example of a real-world migration from Workbox v3 to v4 can be found in this Pull Request.

Getting help

We anticipate most migrations to be straightforward. If you run into issues not covered in this guide, please let us know by opening an issue on GitHub.