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
workbox-precaching
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.precaching.getCacheKeyForURL('fallback.png');
workbox.routing.setCatchHandler(({event}) => {
switch (event.request.destination) {
case 'image':
return caches.match(imageFallbackCacheKey);
break;
// ...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 please 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
.
workbox-strategies
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.
workbox-background-sync
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);
return;
}
}
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.
workbox-expiration
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.
workbox-broadcast-update
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.
workbox-core
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).
workbox-sw
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
workbox-window
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.