This article is shared under a Creative Commons Attribution 4.0 International license, BY Troland.

See Github addresses in updates to this serieshere.

This is chapter 8 of how JavaScript works.

You probably already know that progressive web apps will only become more popular, as they aim to create web apps with a smoother user experience and create app-like native App experiences rather than the look and feel of the browser side.

One of the main requirements for building a progressive web application is that it can be used under various network and data loading conditions – it can be used when the network is unstable or absent.

In this article we’ll take a closer look at Service Workers: how they work and what you should be concerned about. Finally, we will list some unique advantages that Service Workers can take advantage of and share our team practice in SessionStack.

An overview of the

To understand everything about Service Workers, you should first read the previous Web Workers article.

Broadly speaking, a Service Worker is a Web Worker, more like a Shared Worker.

  • The Service Worker runs in its global scripting context
  • Does not specify binding to a web page
  • DOM cannot be accessed

One of the exciting things about the Service Worker interface is that it allows web applications to run offline, giving developers complete control over their web application behavior.

The life cycle

The life cycle of a Service Worker is completely unrelated to the web page. It consists of the following steps:

  • download
  • The installation
  • The activation

download

This occurs when the browser downloads the.js file that contains the Service Worker related code.

The installation

In order to use a Service Worker in a web application, you must first register it in your JavaScript code. When the Service Worker is registered, it tells the browser to start installing the Service Worker in the background.

By registering a Service Worker, the browser knows about the JavaScript file that contains the Service worker-related code. Take a look at this code:

if ('serviceWorker' in navigator) {
  window.addEventListener('load'.function() {
    navigator.serviceWorker.register('/sw.js').then(functionConsole. log('ServiceWorker registration successful');
    }, function(err) {// Failed to register console.log('ServiceWorker registration failed: ', err);
    });
  });
}
Copy the code

The above code first checks whether the current execution environment supports the Service Worker API. If so, register the /sw.js Service Worker.

Register () can be arbitrarily called every time the page loads – the browser checks if the service worker is registered and handles it appropriately.

One area of special attention in the register() method is the address of the Service Worker file. The current example is in the server root. This means that the service worker works on the entire source address. In other words, the service worker receives fetch events for all pages under the domain. If the file path to register the service worker is /example/sw.js, Then the service worker receives fetch events for all urls whose page paths start with /example/ (e.g. /example/page1/ /example/page2/).

During the installation phase, it is a good idea to load and cache some static resources. Once the static resource cache is successful, the installation of the Service Worker is complete. If the load fails -Service Worker will retry. Once installed, static resources are cached.

This answers why the Service Worker should be registered after the load event. This is not necessary, but is highly recommended.

Why do you do that? Assume that the user accesses the network application for the first time. The Service worker is not registered yet, and the browser has no way of knowing in advance whether it will eventually be installed. If installed, the browser will free up extra CPU and memory for additional threads that would otherwise be used to render web pages.

Under referencehere.loadThe event is triggered after all the resources such as images and styles have been loaded.

The end result is that if a Service Worker is installed on a page, it may lead to lazy loading and rendering of the page – not allowing users to access the page as quickly as possible.

Note that this only happens when the page is accessed for the first time. Subsequent page access is not affected by the installation of the Service Worker. Once the Service Worker is activated on the first page visit, it can handle page load/cache events triggered by subsequent page visits. This is true, the Service Worker needs to load well to handle the limited network bandwidth.

The activation

Once installed, the next step is activation. This step is an excellent time to cache resources prior to operation.

Once activated, the Service Worker can begin to control all pages in its scope. An interesting fact is that a page registered with the Service Worker is not processed by the Service Worker until it is reloaded. When the Service Worker takes control, it has the following states:

  • Handles fetch and message events triggered by network or message requests from the page
  • Abort to save memory

The following is its life cycle:

Handles the installation process inside the Service Worker

While the page is running to register the Service Worker, let’s look at what happens in the Service Worker script, which listens for the Install event of the Service Worker instance.

The following steps are required to handle the install event:

  • Open the cache
  • Cache file
  • Verify that all static resources are cached

The following is a possible simple installation code inside a Service Worker:

var CACHE_NAME = 'my-web-app-cache';
var urlsToCache = [
  '/'.'/styles/main.css'.'/scripts/app.js'.'/scripts/lib.js'
];

self.addEventListener('install'.functionEvent.waituntil (caches. Open (CACHE_NAME).then() event.waitUntil(caches.function(cache) {
        console.log('Opened cache');
        returncache.addAll(urlsToCache); })); });Copy the code

If the files are successfully cached, the service worker is successfully installed. If any files fail to download, the service worker will fail to install. Therefore, be aware of the files that need to be cached.

Handling install events is completely optional; skip the above steps when not processing.

Cache runtime requests

This part is dry. Here you can see how to intercept the request and then return the created cache (as well as create a new cache).

When the Service Worker is installed, the user will navigate to another page or refresh the current page, and the Service Worker will receive the FETCH event. Here is an example of how to return a cached static resource or perform a new request and cache the returned result:

self.addEventListener('fetch'.function(event) {event.respondwith (// This method queries the request and returns any cached data created by the Service Worker. caches.match(event.request) .then(function(response) {// If there is a cache, returnif (response) {
          returnresponse; } // Copy the request. A request is a stream and can only be used once. Since it has been used once before through the cache, the request needs to be copied in order to use the FETCH in the browser. var fetchRequest = event.request.clone(); // No cache found. So we need to perform the FETCH to initiate the request and return the request data.return fetch(fetchRequest).then(
          function(Response) {// Check whether the returned data is validif(! response || response.status ! == 200 || response.type ! = ='basic') {
              returnresponse; } // Replication returns data because it is also a stream. Because we want the browser to use the returned data as well as the cache, we have to copy it. Var responseToCache = response.clone(); caches.open(CACHE_NAME) .then(functionCache.put (event. Request, responseToCache) {// Add the request to the cache for future queries. });returnresponse; }); })); });Copy the code

The general process is as follows:

  • event.respondWith()Will decide how to respondfetchEvents.caches.match()The query request then returns any cached data from the previously created cache and returns a promise.
  • If so, the cached data is returned.
  • Otherwise, executefetch
  • Check whether the returned status code is200. Also check whether the response type isbasicThat is, check whether the request is co-domain. The current scenario does not cache requests for third-party resources.
  • Add the returned data to the cache.

Because both the request and response are streams and the stream data can only be used once, replication must occur. And because both caches and browsers need to use them, they must be copied.

Update Service Worker

When a user accesses a web application, the browser tries to re-download the.js file containing the Service Worker code in the background.

If the downloaded file is even slightly different from the current Service Worker code file, the browser will assume that the file has changed and will create a new Service Worker.

The process of creating a new Service Worker will start and the Install event will be triggered. However, at this point, the old Service Worker still controls the web application page, meaning that the new Service Worker will be in a waiting state.

Once the current open page of the web application is closed, the old Service Worker will be killed by the browser and the new Service Worker can take over. The Activate event is triggered.

Why is all this necessary? This is to avoid the problem of running different versions of the web application in different tabs at the same time – something that actually exists on the web and can cause new bugs (such as having a different database structure when storing data locally in the browser).

Delete data from the cache

The most common step in the Activate callback is cache management. Cache management is needed to remove the old cache in the installation step, which will cause the Service Workers to be unable to access the file data in the cache.

Here is an example of how to remove a cache that is not whitelisted (in this case, named page-1 or Page-2) :

self.addEventListener('activate'.function(event) {

  var cacheWhitelist = ['page-1'.'page-2']; Event.waituntil (// Get all keys in the cache caches.keys().then(function(cacheNames) {
      returnPromise.all(// run through all cached files. Cachenames.map (function(cacheName) {// If the cache file is not in the whitelist, delete itif (cacheWhitelist.indexOf(cacheName) === -1) {
            returncaches.delete(cacheName); }})); })); });Copy the code

HTTPS request

Service Workers can be used with localhost while in development, but HTTPS must be deployed when in a publishing environment (which is the last reason to use HTTPS).

Service workers can be used to hijack network connections and forge response data. Without HTTPS, web applications are vulnerable to man-in-the-middle attacks.

To ensure security, Service Workers must be registered on the page through HTTPS, so as to ensure that the Service Worker received by the browser is not tampered with during transmission.

Browser support

Service Workers has good browser compatibility.

You can track all browser support processes:

Jakearchibald. Making. IO/isservicewo…

Service Workers offer the possibility of more functionality

Service Worker’s unique features:

  • Push notifications – Allows users to choose to receive push updates from web applications on a regular basis
  • Background synchronization – Allows delayed operation until the network connection is stable. This ensures that users can send data in real time.
  • Periodic synchronization (later supported) – Provides management for periodic data synchronization in the background
  • Geofencing (future support) – You can customize parameters, known as geofences, that contain the location of interest to the user. Devices are notified when they pass through a geofencing fence, which allows you to provide a useful user experience based on their location.

Each of the features mentioned here will be detailed in future articles in this series.

We are constantly working to make the SessionStack interactive experience as smooth as possible, optimizing page load times and response times.

When replaying a user session or live stream on the SessionStack, the SessionStack interface continuously pulls data from the server to create a class buffering experience for the user (similar to video buffering). A bit more detail on the principle that once the SessionStack library is integrated into a web application, it will continuously collect data such as DOM changes, user interactions, network requests, unhandled exceptions, and debugging information.

When replaying or viewing a session in real time, the SessionStack returns all the data to facilitate viewing of all the events occurring in the user’s browser. (visual and technical). All of this happens in real time because we don’t want users to wait.

Since the data is captured by the front end, Service Workers can be used at this point to handle situations like player reloading and restreaming all the data. Dealing with slow Internet connections is also very important.

See Wikipedia on streamingdefineTo better understand the concept of flow here.

Make an advertisement ^.. ^

Toutiao is hiring! Send resume to [email protected], you can take the fast internal push channel, long-term effective! The JD of the international PGC department is as follows: c.xiumi.us/board/v5/2H… , can also be pushed inside other departments!

See Github addresses in updates to this serieshere.