First address, welcome to pay attention to

If you pursue the ultimate WEB experience, you must have used PWA in your site, and you must have faced hesitation in writing serviceWorker code. Because serviceWorker is so important, once registered in the user’s browser, the whole site will be controlled by serviceWorker. A small problem becomes a big one. But now with Workbox 3, everything about serviceworkers is no longer an issue.

The popular science ServiceWorker

If you’re already familiar with ServiceWorkers, skip this section.

The ServiceWorker is the most important part of the PWA. It is the brain that a website plugs into a user’s browser. This is how ServiceWorker is registered on the page

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/sw.js')}Copy the code

Why is SW (ServiceWorker for short) the brain of the site? For example, if a SW is registered at the root of www.example.com, the SW can control all requests that the browser makes to www.example.com. By simply listening for fetch events, you can manipulate requests arbitrarily, return data read from cacheStorage, initiate new requests through the FETCH API, or even new a Response and return it to the page.

// A bad piece of sw code. After the sw is registered, all requests to the sw control site will return the string "bad", including the HTML of the page
self.addEventListener('fetch'.function(event) {
  event.respondWith(
    new Response('bad')); });Copy the code

Because SW power is too big, it will be like walking on thin ice to write, accidentally some page resources can not be timely and correct update.

A moderately complete ServiceWorker

Let’s start with a direct hand-written SW file

var cacheStorageKey = 'cachesName'
var cacheList = [
  // List of resources to cache immediately after successful registration
]

// The install event is triggered when the browser finishes parsing the sw file
self.addEventListener('install'.function(e) {
  The install event typically pulls the contents of the cacheList to be replaced into the Caches through the addAll method
  e.waitUntil(
    caches.open(cacheStorageKey).then(function(cache) {
      return cache.addAll(cacheList)
    })
  )
})

// Triggers the Activate event when activated
self.addEventListener('activate'.function(e) {
  // Active events usually do some of the work of releasing expired resources, which are removed from caches when matched
  var cacheDeletePromises = caches.keys().then(cacheNames= > {
    return Promise.all(cacheNames.map(name= > {
      if(name ! == cacheStorageKey) {return caches.delete(name);
      } else {
        return Promise.resolve(); }})); }); e.waitUntil(Promise.all([cacheDeletePromises])
  )
})

self.addEventListener('fetch'.function(e) {
  // Write the cache policy here
  e.respondWith(
    // Can be returned by matching resources in the cache
    caches.match(e.request)
    // Can also be pulled from the remote end
    fetch(e.request.url)
    // You can also build your own
    new Response('Make it yourself')
    // The response can also be put into chches by caches. Put)})Copy the code

In fact, all sites SW install and active are similar. They do nothing more than pre-cache resource list and cache cleaning after update. The logic is not too complicated, but the focus is on fetch events. In the above code, I have omitted the fetch event logic, because it would be too much to write carefully, and it would not be helpful to explain the cache policy. Imagine caches where you need to cache different resources with different file extensions, CSS, JS, HTML, images, all requiring a separate cache strategy. You can see how much you need to write in fetch.

Workbox 3

Workbox, defined as a collection of PWA-related tools, has emerged to address this problem, along with a number of other tools such as workbox-cli, gulp-workbox, webpack-workbox-plagin, etc., which are not the focus of today. Today I want to talk about Workbox itself.

Workbox can be thought of as Google’s official PWA framework, which solves the problem of writing PWA using the underlying API. Here said the underlying API, refers to listen to the SW install, active, fetch event to do the corresponding logical processing, etc. Here’s how it works

/ / first introduced importScripts workbox framework (' https://storage.googleapis.com/workbox-cdn/releases/3.3.0/workbox-sw.js'); Workbox. Precaching ([/ / immediately after registering successfully cache resource list]] / / HTML cache strategy workbox. Routing. RegisterRoute (new RegExp (' ' '. * \. HTML), workbox.strategies.networkFirst() ); workbox.routing.registerRoute( new RegExp('.*\.(? :js|css)'), workbox.strategies.cacheFirst() ); workbox.routing.registerRoute( new RegExp('https://your\.cdn\.com/'), workbox.strategies.staleWhileRevalidate() ); workbox.routing.registerRoute( new RegExp('https://your\.img\.cdn\.com/'), workbox.strategies.cacheFirst({ cacheName: 'example:img' }) );Copy the code

It’s much easier to understand the code above, through workbox. Precaching fortress is install later into the contents of the caches of workbox. Routing. The first parameter is a regular in the registerRoute, match after the fetch all requests of events, The workbox. Strategies object provides us with several of the most commonly used strategies, as follows

Stale-While-Revalidate

Cache First

Network First

Network Only

Cache Only

You can extend these policies with plagin, such as adding a cache expiration time (which is officially provided). You can even continue to listen for fetch events and then use these policies. The official documentation is here.

Rule of thumb

After a period of use and thinking, I think the most reasonable, the most conservative cache strategy.

HTML. If you want your page to be accessible offline, use NetworkFirst. If offline access is not required, use NetworkOnly.

CSS and JS, the situation is complicated, because the CSS and JS of general sites are in the CDN, SW has no way to determine whether the resources requested from the CDN are correct (HTTP 200), if the cache failed results, the problem will be big. In this case, I suggest using the stale-while-revalidate strategy to ensure the page speed. Even if the page fails, the user will update it after refreshing.

If your CSS, JS and site are in the same domain, and the file name has the Hash version number, you can use Cache First directly.

It is recommended to use Cache First and set a certain invalidation event. The request will not change once.

These are just general strategies, depending on your opinion.

Also, remember that Cache only and Cache first should never be used for any resource that is not in the same domain.

reference

  • Workbox official documentation
  • Fantastic Workbox 3.0