Workbox is a set of Web App static resources local storage solution by GoogleChrome team. The solution contains some Js libraries and build tools, and is presented for the first time in Chrome Submit 2017. Behind the Workbox are technologies and standards such as Service Worker and Cache API. Prior to Workebox, the GoogleChrome team released sw-precache and sw-toolbox libraries earlier, but from the GoogleChrome engineers’ point of view, workbox is a more perfect solution to handle offline capabilities easily and uniformly. Therefore, I stopped the maintenance of SW-precache and SW-Toolbox.

From the related issues of SW-precache and SW-Toolbox, many developers have complained about them as well. In general, I think the API is too confusing. Although it is very powerful, the design is not clear, and the learning cost makes it difficult to promote. However, from the current documentation and API of workbox3 Alpha, I personally feel that Workbox3 is finally a convenient and simple solution to most of the problems of Service workers, so I write this article to give a comprehensive overview.

Note that workbox 3 is still in the alpha release stage, and the API and interface are subject to change. Some of the tools mentioned in this article may not be fully ready yet. This article is a pre-release version of workbox 3, and will be updated with subsequent releases.

An overview of the

Workbox is now available in 3.0 Alpha. Let’s get to know workbox:

  • No matter how your site is built, it provides offline access to your site.
  • Even if you don’t consider offline capabilities, you can make your site access faster.
  • You don’t have to worry too much about implementation, just configuration.
  • Simple yet flexible, fully customized requirements (support for Service worker-related features such as Web Push, Background sync, etc.)
  • Multiple cache policies for various application scenarios

Bingo! If you’re intrigued by these features, read on. We’re talking about WorkBox 3.0 here. The core issues that WorkBox addresses are the same as the previous version, but the API has been tweaked and the build has been improved. With WorkBox 3.0, the API looks much clearer. Let’s take a look at workbox 3.

usage

To use workBox, you need to create a Service Worker file sw.js in your project and register it on your site:

<script> // Register Service Worker if ('serviceWorker' in navigator) { Can the page load after registration Service Worker window. The onload = function () {the navigator. ServiceWorker. Register ('/sw. Js); }; } </script>Copy the code

To use workBox, you need to import workbox from sw.js:

// Workbox 2.x is to maintain the workbox core content in the workbox-sw node_modules package // workbox 3.x is to maintain the workbox core content in the CDN // Of course can also be moved to its own CDN maintenance importScripts (' https://storage.googleapis.com/workbox-cdn/releases/3.0.0-alpha.3/workbox-sw.js'); if (workbox) { console.log(`Yay! Workbox is the loaded 🎉 `); } else { console.log(`Boo! Workbox didn 't load 😬 `); }Copy the code

What can WorkBox do when you get the workbox global variable in sw.js, indicating that workBox is ready to use?

  • throughworkbox.precachingModule to handle pre-caching of Service Worker static resources.
  • throughworkbox.routingModule provides routing control andworkbox.strategiesThe cache policy control module provides helps you do dynamic cache.
  • Use the Workbox plugin to do some relatively independent work of the Service Worker, such as update reminders, Background Sync, etc

Precache static files

If you have static resources that need to be cached offline forever and not updated until you come online again, precache pre-caching is what you should expect if you know the life cycle of the Service Worker. The precache Work is done through the Cache API when the Service Worker is installed, to learn more about the Service Work lifecycle.

Workbox provides a very convenient API to help solve precache problems, similar to what Google’s previous precache solution, SW-precache, did. Workbox. Through the use of precaching precacheAndRoute interface to complete precache operation:

workbox.precaching.preacheAndRoute([
    '/styles/index.0c9a31.css',
    '/scripts/main.0d5770.js',
    {
        url: '/index.html',
        revision: '383676'
    },
]);
Copy the code

The above code will download /styles/index.0c9a31.css, /scripts/main.0d5770.js, /index.html when the Service Worker is successfully installed. In addition, routes are constructed to store these files in the Cache Storage. The array passed in is essentially a list of cached contents in the form of a string (Hash) with a filename directly written to it, or an object with a URL and revesion value as shown below:

{url: 'url of the file to be cached, revision:' Hash value of the file contents'}Copy the code

Note that the value of this revision is updated when any changes are made to the cached file. If no revision is updated, the cached file will not be updated when you update the Service Worker.

Then we introduce some help us to generate cache content list precaching beforehand. PrecacheAndRoute API configuration options.

To deal with/ 和 /index.html

Normally, when a user accesses /, the page HTML file is /index.html. By default, the precache routing mechanism adds index.html after the/at the end of any URL, This means that any index.html you cache can be accessed via /index.html or /.

Of course, you can also disable this default behavior with the directoryIndex parameter:

workbox.precaching.preacheAndRoute(
    [
        '/styles/index.0c9a31.css',
        '/scripts/main.0d5770.js',
        {
            url: '/index.html',
            revision: '383676'
        },
    ],
    {
        directoryIndex: null
    }
);
Copy the code

Ignoring request parameters

For example, what if we want key1 not to be /example.html? Part of the key1 and key2 = 1 = 2, you only need to set up ignoreURLParametersMatching parameters put it out:

workbox.precaching.precacheAndRoute(
    [
        {
            url: '/example.html?key2=2',
            revision: '6821e0'
        }
    ],
    {
        ignoreUrlParametersMatching:[/key1/],
    }
);
Copy the code

So/example. HTML? The route key1=1&key2=2 can be precached.

Generate a pre-cached list

By manual maintenance precache. PrecacheAndRoute API in the pre cache content list is impossible, revision we cannot manually maintained, so we must be to use some tools to do this thing, but workbox provides a variety of ways to let our choice:

  • Workbox command line
  • Workbox – build NPM package
  • workbox-webpack-plugin

Before using the above three methods to generate the pre-cached content list, we have a preset application scenario: Assuming that your project is in the directory /app, you must ensure that there is an app/sw.js in your project root directory that contains the following content:

/ / sw in the project. Usually js source files are reserved by such an empty array to pre cache content list workbox. Precaching. PrecacheAndRoute ([]);Copy the code

This ensures that the generated pre-cached content list content is injected into the Service Worker file.

Workbox command line

Workbox provides a set of command lines specifically designed to help us inject the pre-cached content list. It can help us to generate the workbox-cli-config.js configuration file needed to inject the pre-cached content list. The command line can then generate a pre-cached list of code using the configuration file and inject it into the previously customized app/sw.js file, and finally compile it into the required Service Worker file online: dist/sw.js.

Install command line:

npm install -g workbox-cli
Copy the code

So we first have a workbox-cli-config.js file, and then from this file combined with the /app/sw.js source file to generate a dist/sw.js file with the pre-cached list. Now we can look at how these processes work.

Workbox generate:sw workbox cli-config.js workbox cli-config.js workbox cli-config.js workbox cli-config.js

>$ workbox generate:sw
? What is the root of your web app? app
? Which file types would you like to cache? (Press <space> to select, <a> to toggle all, <i> to inverse selection)html,ico,svg,png,js,css
? What should the path of your new service worker file be (i.e. './build/sw.js')? dist/sw.js
? Last Question - Would you like to save these settings to a config file? Yes
Copy the code

After answering these questions you can export a new workbox-cli-config.js configuration file in your project that looks something like this:

// workbox-config.js
module.exports = {
    "globDirectory": "app/",
    "globPatterns": [
        "**/*.{html,ico,svg,png,js,css}"
    ],
    "swDest": "dist/sw.js",
    "swSrc": "app/sw.js"
};
Copy the code

Workbox inject:manifest workbox-cli-config.js command to generate compiled dist/sw.js file Workbox-cli-config.js: workbox-cli-config.js: workbox-cli-config.js: workbox-cli-config.js: workbox-cli-config.js: workbox-cli-config.js: workbox-cli-config.js: workbox-cli-config.js The workbox Inject :manifest command is then automatically executed on the configuration in the build script.

workbox inject:manifestThe command is to match
/app/sw.jsIn the
workbox.precaching.precacheAndRoute([])Method regex, which is then injected through the Replace content, as described in the workbox-build section below.

workbox-build

Workbox also provides an NPM package, Workbox-Build, that you can use in any build tool to make precaching easier and more flexible.

To install the workbox-build package, run the following command in your project root directory:

npm install --save-dev workbox-build
Copy the code

You can then directly import the Workbox-build library where you want to handle Service Worker precaching and call its injectManifest method:

const workboxBuild = require('workbox-build'); workboxBuild.injectManifest({ swSrc: path.join(__dirname, 'app', 'sw.js'), swDest: path.join(__dirname, 'dist', 'sw.js'), globDirectory: './dist/', globPatterns: ['**\/*.{html,js,css}'], globIgnores: ['admin.html'], templatedUrls: { '/shell': ['dev/templates/app-shell.html', 'dev/**\/*.css'],}, // To replace the reserved code regular injectionPointRegexp: /(\.precacheAndRoute\()\s*\[\s*\]\s*(\))/, }) .catch(err => { console.error(`Unable to inject the precache manifest into sw.js`); throw err; });Copy the code

Executing this code in the build file reads the app/sw.js file and generates a dist/sw.js file with a list of pre-cached contents for injection.

On how to use
injectManifestYou can view the workbox-build method
injectManifestmethods
All the parameters

workbox-webpack-plugin

Workbox-webpack-plugin workbox-webpack-plugin Workbox-webpack-plugin workbox-webpack-plugin workbox-webpack-plugin workbox-webpack-plugin To install the plugin into your WebPack project:

npm install --save-dev workbox-webpack-plugin
Copy the code

Then you just need to add the plugin to the Webpack configuration to make it work. The plugin parameters are the same as the injectManifest method of workbox-build:

const workboxPlugin = require('workbox-webpack-plugin');

// ...
webpack({
    plugins: [
        // ...
        new workboxPlugin({
            swSrc: './src/sw.js',
            swDest: './dist/sw.js',
            globDirectory: './dist/',
            globPatterns: ['**/*.{html,js,css}'],
        })
    ]
    // ...
});
Copy the code

There is one difference to replacing reserved app/sw.js mentioned earlier: The Webpack plug-in provided with WorkBox must include the following code in app/sw.js to complete the pre-cached content list injection

workbox.precaching.precacheAndRoute(self.__precacheManifest || []);
Copy the code

When the plugin is running, it adds an importScripts() code to /dist/sw.js to introduce a module whose contents are self.__precachemanifest, the contents of a pre-cached list of contents, You can use the workbox-webpack-plugin in your project and see the dist/sw.js result after build.

Routing request cache

Routing request cache is routing through file matching pattern respectively make different strategies to set the routing file cache, this part of the work can be in the app/sw. Use in direct js workbox provide workbox. Routing. RegisterRoute API is complete, This API can be understood as doing two things: first, configuring a match to specify a file or request content to be cached through the request route, and second, deciding which strategy to cache the matched file through the processing callback function of the second parameter. There are three ways to match a request URL with a workbox-route

  • String mode
/ / can be directly under the current project of absolute path workbox. Routing. RegisterRoute ('/logo PNG ', handler / / handler do caching strategies of callback functions, usually refers to the back drop to the 'cache policy function); // Can also be a full URL path with full host, The URL here must be HTTPS workbox. Routing. RegisterRoute (' https://some-host/some-path/logo.png ', handler);Copy the code
  • Regular expression mode
Workbox. Routing. RegisterRoute (new RegExp ('. * \. Js'), / / here is any regular is fine, as long as can match the request routing address handler);Copy the code
  • Callback function mode
Const matchFunction = ({url, event}) => {// Return true if the requested route matches, It is also possible to return a parameter object to be received by the handler. }; workbox.routing.registerRoute( matchFunction, handler );Copy the code

There are three ways to match a request route, and then we can talk about how to handle the content returned by the matched request.

  • Use a workbox to passworkbox.strategiesThe API providesCaching strategies.
  • Provide a custom callback method that returns a Promise with a return result.

Routing request caching policy

Here’s a look at some of the caching policy apis that Workbox provides by default and can be used as handlers.

Stale While Revalidate

If there is no Cache in the first place, the network request will be made and the result will be updated. This is a very secure policy for users, which can ensure that users can get the result of the request as quickly as possible. However, it also has some disadvantages, that is, some network requests still occupy the user’s network bandwidth. The State While Revalidate policy can be used as follows:

Workbox. Routing. RegisterRoute (match, routing workbox. / / matching strategies. StaleWhileRevalidate ());Copy the code

Network First

This strategy is when request routing is matching, using the network strategy, is the first to try to get the network request to return the result, if get the result of the network request, just return the results to the client and write Cache Cache, if network attempt failed, it was finally Cache Cache Cache the results will be returned to the client, This strategy is generally applicable to the request whose return result is not very fixed or has requirements on real-time performance, so as to take the bottom for the failure of network request. The Network First policy can be used as follows:

Workbox. Routing. RegisterRoute (match, / / that match the routing workFirst workbox.strategies.net ());Copy the code

Cache First

If there is no result in the Cache, the network request will be made, the network request will be fetched, the result will be updated to the Cache, and the result will be returned to the client. This strategy is more suitable for the request that the results do not change much and the demand for real-time is not high. The Cache First policy can be used as follows:

Workbox. Routing. RegisterRoute (match, routing workbox. / / matching strategies. CacheFirst ());Copy the code

Network Only

The more direct policy directly forces the normal network request and returns the result to the client. This policy is more suitable for the request with high real-time requirements. The Network Only policy can be used as follows:

Workbox. Routing. RegisterRoute (match, / / that match the routing workOnly workbox.strategies.net ());Copy the code

Cache Only

This strategy is also more direct, directly use the Cache results, and return the results to the client, this strategy is more suitable for static resource requests that do not change once online. The Cache Only policy can be used as follows:

Workbox. Routing. RegisterRoute (match, / / that match the routing workOnly workbox.strategies.net ());Copy the code

Regardless of the strategy, you can customize the routing behavior (how it returns results) by customizing a cache and using or adding plug-ins (we’ll cover the Workbox plug-in later).

Workbox. Strategies. StaleWhileRevalidate ({/ / using the user name of a custom cache cacheName: 'my - cache - the name', / / use workbox plugins plugins: / /... });Copy the code

Of course, these configurations are often required to be more secure when caching requests, that is, to limit the duration of caching or to ensure that the data used on the device is limited.

Custom Policies

If none of the above strategies are sufficient for caching your requests, you’ll need to customize your own strategies and even return different results for different situations. Workbox allows for this scenario (which is why I highly recommend WorkBox). The simplest way is to control the cache policy directly in the Service Worker file via the raw FETCH event. Alternatively, you can use the workbox option by passing in a callback function with an object argument that contains the matching URL and the fetchEvent argument of the request. The callback returns a Response object, as shown below:

workbox.routing.registerRoute( ({url, event}) => { return { name: 'workbox', type: 'guide', }; }, ({url, event, params}) => {// return the result: A guide on workbox return new Response( `A ${params.type} on ${params.name}` ); });Copy the code

Caching of third-party requests

If the domain of a request is inconsistent with that of the current Web site, it can be considered as a third-party resource or request cache. Because Workbox cannot obtain the status of the third-party routing request, Workbox can only cache the error result if the request fails. Therefore, WorkBox 3 does not cache the return results of third-party requests by default. That is, by default the following cache policy does not take effect:

workbox.routing.registerRoute(
    'https://notzoumiaojiang.com/example-script.min.js',
    workbox.strategies.cacheFirst(),
);
Copy the code

Of course, not all policies are inoperable on third-party requests. Workbox 3 allows networkFirst and stalteWhileRevalidate cache policies to take effect because these policies regularly update the cache’s return content. After all, the cache’s contents are updated after each request. Much more secure than direct caching.

Workbox will raise an alarm in the DevTools console if you force third-party requests to be cached using a caching policy not recommended by Workbox 3.

If you still want to cache the results of third-party requests, WorkBox 3 takes into account that there will be a demand that is hard to kill and provides a very human way to meet it: Using workbox. CacheableResponse. The Plugin to specify cache only the result of the request is successful, then drain our previous concerns about unsafe results are cached. Goose sister Ying! (We’ll cover the plugin mechanism later)

workbox.routing.registerRoute( 'https://notzoumiaojiang.com/example-script.min.js', workbox.strategies.cacheFirst({ plugins: / / / this Plugin is to match the request of the eligible for developers to specify the return of the results can be cached new workbox. CacheableResponse. The Plugin ({statuses: [0, 200]})]}),);Copy the code

Workbox configuration

Workbox 3 provides a few configuration items, all packaged in the Workbox. Core API, that you can take a look at.

Configuring the Cache Name

Workbox has some rules for cache naming by DevTools -> Applications -> Caches:

<prefix>-<ID>-<suffix>
Copy the code

Each name has a prefix and a suffix, and the middle is the real named ID. To minimize the possibility of duplicate names, you can customize the precache and Runtime caches as follows:

workbox.core.setCacheNameDetails({ prefix: 'my-app', suffix: 'v1', precache: 'custom-runtime-name',// default value: 'precache' runtime: 'custom-runtime-name' // default value: 'runtime'});Copy the code

After the preceding Settings are configured, the name of the precache cache is my-app-custom-precache-name-

-v1, and the name of the Runtime cache is my-app-custom-runtime-name-

-v1. Workbox recommends setting a different prefix for each of your projects so that you can avoid conflicts when debugging Service workers on your local locahost.

Workbox also provides policy-level cache naming Settings for Web App cache management, which can be set using the cacheName parameter of the policy API:

workbox.routing.registerRoute( /.*\.(? :png|jpg|jpeg|svg|gif)/g, new workbox.strategies.CacheFirst({ cacheName: 'my-image-cache', }) );Copy the code

In this way, the cache for the corresponding image-related cacheFirst policy is named my-image-cache-

. Note that prefix and suffix do not need to be set

Specify the development environment

Debug is required during workbox development, so Workbox 3 also provides logger mechanism to help us troubleshoot problems. However, in production environment, we do not want logger information to be generated, so Workbox provides the setting of “Specify current environment” :

// Set to development mode workbox.setconfig ({debug: true}); // Set to online production mode workbox.setconfig ({debug: false});Copy the code

Configuring log Level

Workbox 3 provides a logger mechanism to help debug workboxes. There are four log levels: DEBUG, log, WARN, and Error.

You can set the log level in the following ways. In this way, you can view only the log information of a certain level, which makes debugging more focused. This is done using the setLogLevel method in the Worbox. Core API:

// Display all log workbox.core.setloglevel (workbox.core.log_levels.debug); Workbox.core. setLogLevel(workbox.core.log_levels.log); // Display only warning and error logs workbox.core.setLogLevel(workbox.core.log_levels.warn); Workbox.core. setLogLevel(workbox.core.log_levels.error); Workbox.core.setloglevel (workbox.core.log_levels.silent); workbox.core.log_levels.silent;Copy the code

Workbox plug-in

The plugin mechanism is probably the biggest improvement in Workbox 3. In 2.x, most of the existing plugins were thrown directly to developers in the form of aN API, leaving developers confused. Now in 3.0, each built-in plugin wraps its own API, solving a separate problem for developers. In addition, WorkBox 3 provides plugin extension mechanisms and event hooks that allow developers to extend plug-ins themselves. The WorkBox plugin allows you to add additional behavior by manipulating the return content and request content within the lifecycle of a request.

The workbox plugin is usually used in the cache policy to make the developer’s cache policy more flexible. Workbox has some built-in plugins:

  • Workbox. BackgroundSync. Plugin: if a network request fails, will request to be added to the background sync queue, and before the next sync an event to launch the request.

  • Workbox. BroadcastUpdate. Plugin: when the Cache Cache update will be broadcast a message to all clients, similar to the sw – register – webpack – what the Plugin.

  • Workbox. CacheableResponse. Plugin: let the match request of returned results can be eligible for developers to specify cache, can pass the status, headers parameter specifies some rules.

  • Workbox. Expiration. Plugin: management of the volume of the Cache and Cache the length of time.

Can be used as shown in the following way workbox plugins to workbox. Expiration. The Plugin, for example:

workbox.routing.registerRoute( /\.(? :png|gif|jpg|jpeg|svg)$/, workbox.strategies.cacheFirst({ cacheName: 'images', plugins: [new workbox. Expiration. Plugin ({maxEntries: 60, / / the largest number of cache, walk over then LRU strategy to remove the old minimum maxAgeSeconds cache usage: 30 * 24 * 60 * 60, / / the cache time for 30 days}), longest],}));Copy the code

Custom plug-in

Of course, WorkBox knew that these plugins would not fit your custom strategy, so we simply exposed the key events throughout the request life cycle as event hook callbacks, meaning that we could use these event hooks to build our own more flexible Workbox plugins. A plugin is a constructor, and hooks are created as constructor methods for developers to customize. Here are some event hooks:

cacheWillUpdate

CacheWillUpdate ({request, response}), which is called just before the result of a request is returned to replace the result of the Cache. You can modify the returned result in this event hook before updating the Cache. If you set the result directly to NULL to avoid the result of the current request being updated to the cache.

cacheDidUpdate

CacheDidUpdate ({cacheName, Request, oldResponse, newResponse}) is called when a new Cache has been written or when the Cache has been updated. You can call this method to do something after the Cache has been updated.

cachedResponseWillBeUsed

CachedResponseWillBeUsed ({cacheName, Request, matchOptions, cachedResponse}), called before the cached result is triggered in the FETCH event and the response is returned, You can use this callback to allow or prevent in-use Cache responses from returning.

requestWillFetch

RequestWillFetch ({request}), which is called when any fetch event is triggered, can modify the requested request content in this destroy.

fetchDidFail

FetchDidFail ({originalRequest, request}), which is called when the fetch event fails to be triggered. The fetch event fails when the network cannot request at all, not when the request returns a non-200 state. You can use this hook to do something when you detect a disconnect.

If you want to write your own workbox plugin, just do the following:

// my-workbox-plugin.js export default const MyWorkboxPlugin = { cacheWillUpdate({request, response}) { // ... }, //... Get on with the businessCopy the code

In this article, we refer to the Official Google documentation for some of our own interpretations and summaries. Interested developers can read the original documentation, which also lists some “best practices” and “debug” methods to help you use WorkBox better.

Finally, you are welcome to pay attention to my wechat public number “Brother Jiang Disorderly Talk”, pay attention to my more articles.

This article is an original article, and it will often update knowledge points and correct some mistakes. Therefore, please keep the original source for reprinting to facilitate traceability, avoid the misleading of old wrong knowledge and have a better reading experience.


Please indicate the source of reprint:
Zoumiaojiang.com/article/ama…