Skip to content

fix(gatsby-plugin-offline): Upgrade workbox to v6 #31542

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 22 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
d8a7d11
Upgraded to workbox v6 / migrated from generateSW/workbox-build to in…
kije May 22, 2021
33b3985
updated documentation
kije May 22, 2021
5455abc
yarn lock update
kije May 22, 2021
87f8c11
added deletePreviousCacheVersionsOnUpdate option to enable cleanup of…
kije May 22, 2021
57866b8
re-added support for `globPatterns` option
kije May 22, 2021
56629c3
updated unit tests
kije May 23, 2021
a338c1e
fixed non-supported Null coalescing operator in node12
kije May 23, 2021
105c354
Merge https://github.com/gatsbyjs/gatsby into 28287-update-workbox-ga…
kije May 23, 2021
d3f495e
use path.resolve for building path to webpack.stats.json
kije May 23, 2021
6c77bf5
clear mocks before each test in onPostBuild tests
kije May 23, 2021
8262d34
add revision to precached files
kije May 24, 2021
8d92147
Merge branch 'master' of https://github.com/gatsbyjs/gatsby into 2828…
kije Jun 8, 2021
e5ef36a
updated yarn.lock
kije Jun 8, 2021
e4cbf28
Merge https://github.com/gatsbyjs/gatsby into 28287-update-workbox-ga…
kije Jun 12, 2021
1d970da
updated yarn.lock
kije Jun 12, 2021
119f057
Merge https://github.com/gatsbyjs/gatsby into 28287-update-workbox-ga…
kije Jun 23, 2021
ceb6704
Merge branch 'master' of https://github.com/gatsbyjs/gatsby into 2828…
kije Jul 25, 2021
cae0722
updated yarn.lock
kije Jul 25, 2021
bd02d7b
Merge branch 'master' of https://github.com/gatsbyjs/gatsby into 2828…
kije Apr 30, 2022
70435a2
(chore) lint fixes
kije Apr 30, 2022
3928d4d
(chore) changelog update & fixed documentation
kije Apr 30, 2022
ea684e3
(feature) ported changes & new features from gatsby-plugin-offline-ne…
kije May 1, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion packages/gatsby-plugin-offline/.gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/*.js
!index.js
/serviceworker/*.js
!/index.js
!src/__tests__/fixtures/public
yarn.lock
11 changes: 11 additions & 0 deletions packages/gatsby-plugin-offline/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,17 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.

## 6.0.0 (UNRELEASED)

- Upgraded workbox from v4.x to v6.x
- No longer uses workbox-build/generateSW. public/sw.js is now generated during the build-javascript stage via the workbox-webpack-plugin
- precache resources gathered from built pages is no longer inlined in the sw.js itself, but written after the build to a separate file that gets included via importScripts in the service worker. The file name contains a content hash to ensure that a service worker update is triggered it it's content changes
- default runtime caching handlers: only cache successful (HTTP status 200) responses
- added deletePreviousCacheVersionsOnUpdate for cleaning up old cache versions in case cacheId changes
- ⚠️ breaking changes to the structure of the options of this plugin due to workbox upgrade -> see [Upgrading to 6.x](https://github.com/gatsbyjs/gatsby/blob/master/packages/gatsby-plugin-offline/README.md#upgrading-to-6x)

**Note:** Version bump only for package gatsby-plugin-offline

## [5.13.0](https://github.com/gatsbyjs/gatsby/commits/[email protected]/packages/gatsby-plugin-offline) (2022-04-26)

[🧾 Release notes](https://www.gatsbyjs.com/docs/reference/release-notes/v4.13)
Expand Down
282 changes: 212 additions & 70 deletions packages/gatsby-plugin-offline/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ plugins: [`gatsby-plugin-offline`]

## Available options

In `gatsby-plugin-offline` 3.x, the following options are available:
In `gatsby-plugin-offline`, the following options are available:

- `precachePages` lets you specify pages whose resources should be precached by the service worker, using an array of globs. For example:

Expand All @@ -38,14 +38,14 @@ In `gatsby-plugin-offline` 3.x, the following options are available:

Note: while essential resources of specified pages will be precached, such as JavaScript and CSS, non-essential resources such as fonts and images will not be included. Instead, these will be cached at runtime when a user visits a given page that includes these resources.

- `appendScript` lets you specify a file to be appended at the end of the generated service worker (`sw.js`). For example:
- `swSrc` lets you specify a file that is used as the entry point of the service worker (`sw.js`). For example:

```javascript:title=gatsby-config.js
plugins: [
{
resolve: `gatsby-plugin-offline`,
options: {
appendScript: require.resolve(`src/custom-sw-code.js`),
swSrc: require.resolve(`src/custom-sw-code.js`),
},
},
]
Expand All @@ -54,118 +54,260 @@ In `gatsby-plugin-offline` 3.x, the following options are available:
<br />

```javascript:title=src/custom-sw-code.js
// default workbox setup & logic from `gatsby-plugin-offline/serviceworker/index.js`:
import { precache } from "gatsby-plugin-offline/serviceworker/precache.js"
import { setup } from "gatsby-plugin-offline/serviceworker/setup.js"
import { registerDefaultRoutes } from "gatsby-plugin-offline/serviceworker/default-routes.js"
import { setupOfflineRouting } from "gatsby-plugin-offline/serviceworker/offline.js"
import { googleAnalytics } from "gatsby-plugin-offline/serviceworker/google-analytics.js"
import { cleanup } from "gatsby-plugin-offline/serviceworker/cleanup.js"
import { NavigationRoute, registerRoute } from "workbox-routing"

precache()
setup()
registerDefaultRoutes()
setupOfflineRouting()
googleAnalytics()
cleanup()

// custom code:

// show a notification after 15 seconds (the notification
// permission must be granted first)
setTimeout(() => {
self.registration.showNotification("Hello, world!")
}, 15000)

// register a custom navigation route
const customRoute = new workbox.routing.NavigationRoute(({ event }) => {
const customRoute = new NavigationRoute(({ event }) => {
// ...
})
workbox.routing.registerRoute(customRoute)
registerRoute(customRoute)
```

- `debug` specifies whether Workbox should show debugging output in the browser console at runtime. When undefined, defaults to showing debug messages on `localhost` only.
The specified file will be compiled/bundled with webpack, so as shown in the example above, other modules can be imported.

- `workboxConfig` allows you to override the default Workbox options - see [Overriding Workbox configuration](#overriding-workbox-configuration). For example:
Note: if you provide the `swSrc` option, you'll need to make sure that the appropriate workbox routes get set up
and also the custom offline logic this plugin provides gets executed. See files in `gatsby-plugin-offline/serviceworker` for further information

```javascript:title=gatsby-config.js
plugins: [
{
resolve: `gatsby-plugin-offline`,
options: {
workboxConfig: {
importWorkboxFrom: `cdn`,
},
},
},
]
```
- `cacheId` lets you specify a custom cache prefix used by workbox. See [Configure Workbox Documentation](https://developers.google.com/web/tools/workbox/guides/configure-workbox)

- `define` Object passed to webpack's DefinePlugin to define values that get replaced in the compiled service worker. See [DefinePlugin](https://webpack.js.org/plugins/define-plugin/)

- `webpackCompilationPlugins` Optional webpack plugins that will be used when compiling the swSrc input file. See [InjectManifest options](https://developers.google.com/web/tools/workbox/reference-docs/latest/module-workbox-webpack-plugin.InjectManifest#InjectManifest)

- `chunks` additional webpack chunk names that shall be precached. See [InjectManifest](https://developers.google.com/web/tools/workbox/reference-docs/latest/module-workbox-webpack-plugin.InjectManifest) for more information

- `offlineAnalyticsConfig` If specified, these options get passed to the [workbox-google-analytics](https://developers.google.com/web/tools/workbox/reference-docs/latest/module-workbox-google-analytics) plugin. You can also set this option to just enable this plugin with the default options

- `deletePreviousCacheVersionsOnUpdate` If set to true, automatically attempts to delete previous caches on service worker update if `cacheId` has changed. Useful if you're `chacheId` might change, and you want to avoid old, unused caches form taking up space on the user's device.

- `cleanupOutdatedCaches` If set to true, automatically cleans up outdated caches from older workbox versions. See [workbox's documentation](https://developers.google.com/web/tools/workbox/reference-docs/latest/module-workbox-precaching?hl=en#.cleanupOutdatedCaches)

- `globPatterns` A set of optional glob patterns to include in precaching.

- `lodashWebpackPluginFeatures` Configuration of enabled lodash feature sets. See [lodash-webpack-plugin](https://github.com/lodash/lodash-webpack-plugin#feature-sets)

- `additionalManifestEntries`, `manifestTransforms`, `maximumFileSizeToCacheInBytes`, `dontCacheBustURLsMatching`, `modifyURLPrefix` Options passed to [workbox's InjectManifest webpack plugin](https://developers.google.com/web/tools/workbox/reference-docs/latest/module-workbox-webpack-plugin.InjectManifest)

## Upgrading to 6.x

## Upgrading from 2.x
Version 6.x of this plugin no longer uses the `workbox-build`/`generateSW` tool to generate the service worker.
Instead, it uses the `InjectManifest` webpack plugin.
This means that some options are no longer supported (although it should be possible to implement the same features via a custom `swSrc` -> see above).

To upgrade from 2.x to 3.x, move any existing options into the `workboxConfig` option. If you haven't specified any options, you have nothing to do.
To upgrade from a version prior to 6.x (3.x, 4.x, 5.x), you'll need to perform the following steps:

For example, here is a 2.x config:
1. Remove no longer supported options `importWorkboxFrom` and `globDirectory`

2. Move supported options from `workboxConfig` to the root level option object

```javascript
plugins: [
{
resolve: `gatsby-plugin-offline`,
options: {
importWorkboxFrom: `cdn`,
precachePages: ["about"],
workboxConfig: {
cacheId: "some-cache-id",
offlineGoogleAnalytics: true,
cleanupOutdatedCaches: true,
directoryIndex: "index.html",
importWorkboxFrom: "cdn",
},
},
},
]
```

Here is the equivalent 3.x config:

```javascript
plugins: [
{
resolve: `gatsby-plugin-offline`,
options: {
precachePages: ["about"],
cacheId: "some-cache-id",
offlineGoogleAnalytics: true,
cleanupOutdatedCaches: true,
directoryIndex: "index.html",
},
},
]
```

3. The `runtimeCaching` option is no longer supported in 6.x.
If you previously used custom `runtimeCaching` handlers, you'll need to create a custom `swSrc` file to archive the same effect.

<br />

In case you just added some additional handlers without modifying the default handlers provided by `gatsby-plugin-offline`,
this should be straight forward:

```javascript:title=old-gatsby-config.js
// previous
plugins: [
{
resolve: `gatsby-plugin-offline`,
options: {
workboxConfig: {
importWorkboxFrom: `cdn`,
runtimeCaching: [
// Default handlers from gatsby-plugin-offline
{
// Use cacheFirst since these don't need to be revalidated (same RegExp
// and same reason as above)
urlPattern: /(\.js$|\.css$|static\/)/,
handler: `CacheFirst`,
},
{
// page-data.json files, static query results and app-data.json
// are not content hashed
urlPattern: /^https?:.*\/page-data\/.*\.json/,
handler: `StaleWhileRevalidate`,
},
{
// Add runtime caching of various other page resources
urlPattern: /^https?:.*\.(png|jpg|jpeg|webp|avif|svg|gif|tiff|js|woff|woff2|json|css)$/,
handler: `StaleWhileRevalidate`,
},
{
// Google Fonts CSS (doesn't end in .css so we need to specify it)
urlPattern: /^https?:\/\/fonts\.googleapis\.com\/css/,
handler: `StaleWhileRevalidate`,
},

// Your custom handler
{
urlPattern: /my-custom-pattern/,
handler: `NetworkFirst`,
},
],
},
},
},
]
```

In version 3, Workbox is also upgraded to version 4 so you may need to update your `workboxConfig` if any of those changes apply to you. Please see the [docs on Google Developers](https://developers.google.com/web/tools/workbox/guides/migrations/migrate-from-v3) for more information.
```javascript:title=new-gatsby-config.js
// 6.x
plugins: [
{
resolve: `gatsby-plugin-offline`,
options: {
// ...
swSrc: path.resolve(__dirname, "src/custom-sw.js"),
},
},
]
```

## Overriding Workbox configuration
```javascript:title=src/custom-sw.js
// this includes the default behaviour & setup of the service worker from gatsby-plugin-offline
import "gatsby-plugin-offline/serviceworker/index.js"

When adding this plugin to your `gatsby-config.js`, you can use the option `workboxConfig` to override the default Workbox config. To see the full list of options, see [this article on Google Developers](https://developers.google.com/web/tools/workbox/modules/workbox-build#full_generatesw_config).
import { registerRoute } from "workbox-routing"
import { NetworkFirst } from "workbox-strategies"

The default `workboxConfig` is as follows. Note that some of these options are configured automatically, e.g. `globPatterns`. If you're not sure about what all of these options mean, it's best to leave them as-is - otherwise, you may end up causing errors on your site, causing old files to be remain cached, or even breaking offline support.
// your custom handler goes here
registerRoute(/my-custom-pattern/, new NetworkFirst(), `GET`)
```

```javascript
const options = {
importWorkboxFrom: `local`,
globDirectory: rootDir,
globPatterns,
modifyURLPrefix: {
// If `pathPrefix` is configured by user, we should replace
// the default prefix with `pathPrefix`.
"/": `${pathPrefix}/`,
},
cacheId: `gatsby-plugin-offline`,
// Don't cache-bust JS or CSS files, and anything in the static directory,
// since these files have unique URLs and their contents will never change
dontCacheBustURLsMatching: /(\.js$|\.css$|static\/)/,
runtimeCaching: [
{
// Use cacheFirst since these don't need to be revalidated (same RegExp
// and same reason as above)
urlPattern: /(\.js$|\.css$|static\/)/,
handler: `CacheFirst`,
},
{
// page-data.json files, static query results and app-data.json
// are not content hashed
urlPattern: /^https?:.*\/page-data\/.*\.json/,
handler: `StaleWhileRevalidate`,
},
{
// Add runtime caching of various other page resources
urlPattern:
/^https?:.*\.(png|jpg|jpeg|webp|svg|gif|tiff|js|woff|woff2|json|css)$/,
handler: `StaleWhileRevalidate`,
<br />

If you have previously overwritten or modified the default handlers from `gatsby-plugin-offline`, you'll need a bit more code in your `swSrc`:

<br />

```javascript:title=old-gatsby-config.js
// previous
plugins: [
{
resolve: `gatsby-plugin-offline`,
options: {
workboxConfig: {
runtimeCaching: [
// Default handlers from gatsby-plugin-offline
{
// *modified*
// Use cacheFirst since these don't need to be revalidated (same RegExp
// and same reason as above)
urlPattern: /(\.js$|\.css$|static\/|\.wasm$)/,
handler: `StaleWhileRevalidate`,
},
{
// *not modified*
// page-data.json files, static query results and app-data.json
// are not content hashed
urlPattern: /^https?:.*\/page-data\/.*\.json/,
handler: `StaleWhileRevalidate`,
},
],
},
},
{
// Google Fonts CSS (doesn't end in .css so we need to specify it)
urlPattern: /^https?:\/\/fonts\.googleapis\.com\/css/,
handler: `StaleWhileRevalidate`,
},
]
```

```javascript:title=new-gatsby-config.js
// 6.x
plugins: [
{
resolve: `gatsby-plugin-offline`,
options: {
// ...
swSrc: path.resolve(__dirname, "src/custom-sw.js"),
},
],
skipWaiting: true,
clientsClaim: true,
}
},
]
```

```javascript:title=src/custom-sw.js
// code based on gatsby-plugin-offline/serviceworker/index.js (note: `registerDefaultRoutes()` is not used, as we will define all used route handlers below ourselfs)
import { precache } from "gatsby-plugin-offline/serviceworker/precache.js"
import { setup } from "gatsby-plugin-offline/serviceworker/setup.js"
import { setupOfflineRouting } from "gatsby-plugin-offline/serviceworker/offline.js"
import { googleAnalytics } from "gatsby-plugin-offline/serviceworker/google-analytics.js"
import { cleanup } from "gatsby-plugin-offline/serviceworker/cleanup.js"
import { NavigationRoute, registerRoute } from "workbox-routing"
import { registerRoute } from "workbox-routing"
import { StaleWhileRevalidate } from "workbox-strategies"

precache()
setup()
setupOfflineRouting()
googleAnalytics()
cleanup()

// your custom/modified handlers go here. Note: you'll need to specify all handlers manually, even those you didn't modify previously
registerRoute(
/(\.js$|\.css$|static\/|\.wasm$)/,
new StaleWhileRevalidate(),
`GET`
) // modified handler
registerRoute(
/^https?:.*\/page-data\/.*\.json/,
new StaleWhileRevalidate(),
`GET`
) // unmodified default handler
```

## Remove
Expand Down
Loading