Indulge in the beauty of life. Look at the stars and imagine yourself riding with them. — Marcus Aurelius, philosopher

  • Wechat official account “JavaScript Full Stack”
  • Nuggets’ Master of One ‘
  • Bilibili, The Master of One

Performance is always a tradeoff in time and space, and optimization of computer systems requires a variety of caching strategies, from CPU to memory, from interfaces to peripherals. If one day hardware cost and implementation difficulty are no longer obstacles, there may be no such thing as “optimization.”

At present, the front-end is facing more optimization and challenges, complex terminal environment, a variety of different browser kernels, different sizes of browsing devices, compatibility to do. Complex and unstable network environment, more and more resources, optimization to do. We are not unfamiliar with caching, but we want to have subjective caching. We can decide what we want to cache, how long we want to cache, and what the strategy of caching and requesting resources is. The service worker can help us do this.

To use a service worker, you need to create a registration file. You can create a file called sw.js under your project

console.log('Hello, I am sw.js file')
Copy the code

Then register the service worker in the application through this file. The following code can complete the registration of the service worker in the application. The subsequent processing related to the service worker will be carried out in the sw.js file

<script>
	// Check whether the current browser supports service workers
  if ('serviceWorker' in navigator) {
    // Make sure the resource is loaded before registering the service worker
    window.addEventListener('load', () => {
      navigator.serviceWorker.register('/sw.js');
    });
  }
</script>
Copy the code

Refresh the page and you can see that the console prints this sentence indicating that the service worker was successfully registered

Open the console Application and everything is under control. The service worker has been registered successfully

The service worker has been registered. For its configuration and processing, let’s define it in sw.js file.

Google’s standard unified API, Service Worker-based policy cache library has a few nice features

  1. Precaching
  2. Runtime caching
  3. Strategies
  4. Request routing
  5. Background sync
  6. Helpful debuggin
  7. Greater flexibility and feature set than sw-precache and sw-toolbox

I think of a sentence, simple concept complicated, popular concept mystery, this is to show their extraordinary, 😆, a joke. I believe that most people see these concepts as confusing, we just need to focus on one concept: caching, and it is strategic, and what can be controlled, but also gives us ideas for developing offline applications.

Using Workbox

Remember that sw.js file? Now we’re going to focus on it, because we’re going to do all the related stuff in this file. Ready? Go!

# # # import Workbox

Import workbox.js in the first line of sw.js with the following syntax

importScripts('https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js');
Copy the code

Does that make the import successful? Write some code to test it out!

if (workbox) {
  console.log(`Yay! Workbox is the loaded 🎉 `);
} else {
  console.log(`Boo! Workbox didn 't load 😬 `);
}
Copy the code

After the changes are completed, I will go back to the browser and refresh the browser without any changes. Here I need to remind you that after changing the service worker registration file, you need to terminate, restart or update it.

Get started with Workbox

Workbox defines a standard unified API. How can we use the API provided by Workbox to gradually optimize the project

Route request definition cache

In Workbox, the core concept is route-based policy caching. The key words here are route-based and policy caching. The next step is to focus on how to implement policies based on routing.

Most of the front-end resources are obtained through HTTP requests, including JS, CSS, images and so on. Since these contents need to be requested, can I do some processing after the request is issued? Just like the landlord renting a house, the information between the landlord and the tenant may be asymmetric, then the intermediary appears, it can do some processing before the landlord rents the house, such as adding intermediary fees. When a web page initiates a resource request, we can also make some decisions about whether to take it from the cache or request it. For different resources, it is the resource request address that is implemented, which is __ based on route __, as shown in the following example

workbox.routing.registerRoute(
  /\.js$/,...). ;Copy the code

In this code, we define a routing caching policy, that is, all requests with the suffix.js will be processed in this policy. What processing should we do? There will be different caching policies defined for resources that match the route, for example, we require that resource network requests be specified first

workbox.routing.registerRoute(
  /\.js$/.new workbox.strategies.NetworkFirst()
);
Copy the code

This cache will take effect if a JS file is introduced in the project, assuming that the project introduces hello.js

console.log('hello js file')
Copy the code

Introduced in HTML

<script src="./hello.js"></script>
Copy the code

Update the service worker when you go to the browser. Following the refresh, we can see the printed log indicating that the configuration was successful

All things are difficult at the beginning, so we have overcome the first problem. Now we will expand horizontally and choose different strategies for different types of file configuration. Let’s start by looking at the configuration for handling different files, which is very simple

String mode
workbox.routing.registerRoute(
    '/logo.png',
    handler // handler is a callback to the cache policy, usually referred to as' cache policy function '.
);
workbox.routing.registerRoute(
    'https://some-host/some-path/logo.png',
    handler
);
Copy the code
Regular expression
workbox.routing.registerRoute(
  // Cache images./ \. (? :png|jpg|jpeg|svg|gif)$/, handler );Copy the code
Functional form
// Use the function to match the request route
const matchFunction = ({url, event}) = > {
    // Return true if the request route matches, or return a parameter object for the handler to receive
    return false;
};

workbox.routing.registerRoute(
    matchFunction,
    handler
);
Copy the code

The handler for this code is a cache policy API provided by WorkBox

Policy name API
staleWhileRevalidate If the requested route has the corresponding Cache result, it will directly return. When the Cache result is returned, the network request will be sent in the background to get the request result and update the Cache. If there is no Cache, the network request will be sent directly and return the result
networkFirst Network first policy
cacheFirst The result is fetched directly from the Cache. If there is no result in the Cache, the network request is made, the network request is fetched, the result is updated to the Cache, and the result is returned to the client
networkOnly Force a normal network request to be used
cacheOnly Use the cached result directly

In common scenarios, the preceding five policies can meet the requirements. If the requirements are not met, you can customize policies

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

Here is an example of how to use different policies

For example, image resources, which do not change very often, can be grouped under Application -> Cache

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

Js and other relevant files can be appropriately selected network priority

workbox.routing.registerRoute(
  /\.html$/.new workbox.strategies.NetworkFirst()
);

workbox.routing.registerRoute(
  /\.js$/.new workbox.strategies.NetworkFirst({
    networkTimeoutSeconds: 3,}));Copy the code

Workbox is used in Webpack

First install the Workbox-webpack-plugin and choose to use the NPM installation

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

Configure the plug-in in the WebPack configuration file

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

To use the Webpack plug-in provided by Workbox, you 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

At this point, can you imagine supporting offline access through our configuration of resources in the project? These configurations can greatly improve application performance, policy, and you want the best.

I am one, farewell hero!