service worker

The HTML5 standard introduces Webworker, which is JavaScript that runs in the background, independent of other scripts, and does not affect page performance. Service Worker is an implementation of Web Worker and acts as a local proxy server for Web applications. After registering a Service Worker on a particular path, we can intercept and process all network requests under that path. In this paper, we use this proxy mechanism to implement programmable caching of web page core resources.

Basic usage

1. Register

navigator.serviceWorker.register('your_service_worker.js', {scope: 'your-path-name'}).then(function (registration) {
    console.log('succeeded');
}).catch(function (error) {
    console.log('error' + error);
});

Copy the code

The register method takes two parameters, the first is the file path of the service worker, the second is the configuration item of the service worker, where the scope property controls the service worker working directory. The default is the file directory where the service worker resides. Multiple Service workers can be registered under the same Origin, but the Scope cannot be the same.

2. Log out

navigator.serviceWorker.getRegistration('your_service_worker.js', {scope: 'your-path-name'}).then(function (registration) {
    if (registration && registration.unregister) {
        registration.unregister().then(function (isUnRegistered) {
            if (isUnRegistered) {
                console.log('unRegistration succeeded.');
            } else {
                console.log('unRegistration failed.'); }}); } ).catch(function (error) {
    console.log('[SW]: UnRegistration failed with. ' + error);
});
Copy the code

You need to obtain the service woker using getRegistration, and then unregister the service woker by calling the unregister method.

3. Event monitoring

// Install listener
this.addEventListener('install'.function (event) {
  console.log('Service Worker install');
});

// Activate the listener
this.addEventListener('activate'.function (event) {
  console.log('Service Worker activate');
});
Copy the code

The life cycle

Installing

Once the service worker is registered, the browser downloads it and parses it. By default, the service worker is downloaded every 24 hours.

Activating & Activated

After the script is installed, the service worker enters the Activating and Activated states. Failure leads to the Redundant state.

Redundant

This state occurs when Installing or Activating fails, and also when the old service worker is replaced by the new service worker.

communication

From pages to Service workers

if ('serviceWorker' in window.navigator) {
  navigator.serviceWorker.register('your_service_worker.js', { scope:'your-path-name' })
    .then(function (reg) {
      navigator.serviceWorker.controller && navigator.serviceWorker.controller.postMessage("hello");
    });
}

Copy the code

From service worker to page

First, listen for the message from the page, based on the message from the page to get the event.source.

this.addEventListener('message'.function (event) {
  event.source.postMessage('this message is from sw.js, to page');
});
Copy the code

Static resource caching

Finally, the main point of this article is that almost all static resources including CSS, JS, images, etc. can be cached in Service workers. Generally, the service Worker is used to cache resources

1. After the service worker is successfully installed, it caches the required resources
this.addEventListener('install'.function (event) {
  event.waitUntil(
    caches.open('my_sw_cache').then(function (cache) {
      return cache.addAll([
        '/'.'/script/style.css',])})); });Copy the code

Use the caches. Open method to create or open an existing cache, and the cache.addAll method requests connected resources and stores them in the cache. Using event.waitUntil can ensure that the Service Worker will not be installed until the resource is cached to avoid errors.

2. Listen to all the fetch requests of the browser and use the local cache to return cached resources.
this.addEventListener('fetch'.function(event) {
  event.respondWith(
    caches.match(event.request)
      .then(function(Response) {// The fetch request has been cachedif (response) {
          return response;
        }
        returnfetch(event.request); })); });Copy the code

3. Version control

As mentioned above, with the new service worker, the pages of the old version will all be closed. At this point, we need to clear the old cache. How to identify and find the old version of the cache is the key. CacheStorage provides a simple API for finding old cache resources. CACHE_PREFIX indicates the application cache prefix, and CACHE_VERSION indicates the current cache version.

function deleteCache() {
    return caches.keys().then(function (keys) {
        var all = keys.map(function (key) {
            if(key.indexOf(CACHE_PREFIX) ! = =- 1 && key.indexOf(CACHE_VERSION) === - 1) {console.log('Delete success-->' + key);
                  returncaches.delete(key); }});return Promise.all(all);
    });
}
Copy the code

Whitelist control

Not all old caches are not needed. Some caches can be used all the time, so a whitelist needs to be set up to remove caches that are not in the whitelist when the Service Worker is activated.

const noDelete = ['you_no_delete_source.js'] / / white list
function deleteCache() {
    return caches.keys().then(function (keys) {
        var all = keys.map(function (key) {
            if(key.indexOf(CACHE_PREFIX) ! = =- 1 && key.indexOf(CACHE_VERSION) === - 1 && !noDelete.includes(key)){
                  console.log('Delete success-->' + key);
                  returncaches.delete(key); }});return Promise.all(all);
    });
}
Copy the code

conclusion

The code above is just a demo implementation, but the actual situation may be much more complicated, such as

1. What resources need to be cached is not artificially controlled. More often, it is the files generated by Webpack, so a set of regular matching rules need to be generated to identify different files, which files need to be cached, and for how long.

2. Improper cache control may lead to disastrous consequences. If the user can not get the correct corresponding results, it may lead to no response on the page, data confusion and various errors. Therefore, additional processing is needed for the response error code, such as avoiding the cache of 304,404,xx and other contents that do not need to be cached.