The first article, wrote for a long time, a lot of original parts, hope to help you. Please give me your advice.

Introduction of PWA

PWA, the full name of Progressive Web Application, does not refer to a specific technology, but can be regarded as a collection of some new technologies. PWA is essentially a Web App. With the help of new technologies, it has some features of Native apps.

Bright spot

The advantages of PWA are listed in MDN, which mainly improve the pain points of current Web App. The following are some of the features of THE PWA.

Progressive

The technologies are not dependent on each other and can be implemented independently. If a technology is not supported on the client side, it is not valid, period. You don’t need to break your application’s backward compatibility to implement new features.

The main considerations for adopting gradualism are as follows:

  • Can reduce the cost of site transformation
  • Support for the new technical standard is not complete and the standard has not been finalized

Connectivity Independent

With the Service Worker, you can work offline or at low network speeds.

Installable

Allows users to add applications to the desktop.

Re-engageable

Message Push is implemented through the Web Push API, and Notifications API is implemented on the desktop to attract users to revisit from outside the browser.

PWA Checklist

The PWA Checklist provides the standards that PWA applications can refer to. In addition to reading this standard, you can also analyze Web applications through Lighthouse Tool to get improvement suggestions for PWA.

Related core technologies

  • Web App Manifest
  • Service Worker
  • Notifications API
  • Push API

Example – Douban PWA

If you have read the PWA Checklist above, you may have noticed that many existing websites already have some PWA capabilities (e.g. HTTPS, responsive). However, as a programmer who pursues a little bit, only the Web App that uses the core technologies such as Service Worker and App Manifest can qualify as a real PWA in my heart.

To measure whether a Web App is PWA by this standard, at present, the main domestic manufacturers using PWA technology include Douban mobile version, Weibo mobile version, Ele. me -H5, and Alibaba (International) -mobile version. If you’re careful, you’ll notice that these apps are mobile. If we consider that THE emergence of PWA is to enable Web apps to have certain Native App capabilities (such as offline use, notification push), and these capabilities can play a greater value on mobile, it may not be difficult to understand why manufacturers use PWA technology on mobile in the first place. (There are also websites like Vue and Gmail that offer PWA on PC, as these technologies are also useful on PC, but are more obvious on mobile).

You can find PWA apps on Outweb and Appscope, two sites that catalog PWA apps.

Let’s take douban mobile version as an example to feel the difference between PWA and traditional Web App.

First let’s run a score with the Lighthouse Tool mentioned above.

Well, the PWA individual score is 91, which seems pretty good, but it’s not intuitive enough, so let’s look at the program.

Figure (a) – (f) is a screenshot of douban Mobile using Android’s Chrome browser. Manifest (A-E) and Service Worker (F) are mainly involved here.

Entry page for the first time, the browser will be prompted to add applications to the main screen (a), click add (b), mobile phones watercress is generated on the desktop version of the icon (c), click on the desktop icon into the page again, you can see the application of the welcome screen, the browser’s address bar will also disappear (d). At this time, if you check the background application, you can find that the current page in the system process is displayed in the name of “Douban (mobile version)” rather than “Chrome browser” (e). Turn off mobile data and wireless network. After refreshing the page, you can still browse the previous content (f).

Service Worker

The predecessor

Service workers are associated with two other technologies: Web workers and Application Cache.

The browser’s JavaScript runs on a single main thread, and as businesses become more complex, performance issues become more prominent. W3C proposed the Web Worker API. Some time-consuming and resource-consuming tasks will be assigned to this API. After completion, the main thread will be notified through post Message method, and the main thread will get feedback results through onMessage method. However, Web workers are temporary, and the operations performed each time cannot be persisted, which cannot solve the problem of time consuming for repeated access. On this basis, Service Worker is proposed to add persistent offline cache capability on the basis of Web Worker.

Application Cache is an Application caching mechanism introduced early in HTML5. The standard also attempts to make applications available offline. However, it has been removed from Web standards due to developers’ inability to effectively control the cache and other flaws in the update logic.

What can a Service Worker do?

  • Intercepting network requests
  • Returns the cache contents when the cache is available
  • Manage the cache content
  • Push information to the client
  • Background data synchronization
  • Resources prefetching

The characteristics of

  • Must work in HTTPS environment
  • Separate thread with its own worker context
  • Automatically wake up when in use and automatically sleep when not in use
  • You cannot manipulate the DOM directly
  • Asynchronous implementation, mostly implemented internally through promises

Related,

  • HTTPS
  • Promise
  • Fetch API (Fetch resources)
  • Cache API
  • Push API

compatibility

As of now (2018-08-30), about 83.89% of browsers support Service workers.

Life cycle approach

The Service Worker lifecycle can be roughly divided into four phases.

  • The Parse analytical
  • Install the installation
  • Activate the activation
  • Redundant abandoned

Parse

A Service Worker is an object mounted to the Navigator. Before using it, check its availability and register the Service Worker if it is available. Always keep in mind that the Service Worker needs to work in HTTPS, otherwise the registration will fail unconditionally.

if ('serviceWorker' in navigator) {
    navigator.serviceWorker
            .register('service-worker.js')
            .then(function() { console.log('Service Worker Registered');
    });
}
Copy the code

The register() method has an optional parameter, scope, that specifies which directory (scope) the Service Worker controls to cache files in. If left unfilled, this defaults to the directory where the Service Worker files are stored.

.register('service-worker.js', {scope: '/'})
Copy the code

The successful registration will be visible in the Service Worker under the Chrome Console Application.

Install

const PRECACHE_URLS = [".. /".".. /styles/index.css".".. /scripts/index.js"]

self.addEventListener("install", event => {
  event.waitUntil(
    caches
      .open('shell')
      .then(cache => cache.addAll(PRECACHE_URLS))
      .then(self.skipWaiting())
  )
})
Copy the code
  1. Self.skipwaiting () is used to skip the wait state. This method mainly involves the process of installing a new Service Worker and disposing the old Service Worker, i.e. updating the Service Worker. Normally, the new Service Worker will be put into a wait state after it has been installed and will not be replaced until the old Service Worker stops working (usually by closing the browser).
  2. Since the system hibernates the Service Worker at any time, to prevent interruption of execution, you need to use event.waituntil () for capture, which listens for promises returned by asynchronous requests. If there are reject cases, The Service Worker fails to be started.

To prevent the Service Worker from failing to start due to a large or unstable file download failure, only some files can be returned through cache.addall ().

self.addEventListener('install'.function(event) {
  event.waitUntil(
    caches.open('shell').then(function(cache) {// load cache.addall (//...) ; // Stable file or small file loadingreturncache.addAll( // ); })); });Copy the code

The first cache.addall () will not be captured.

Activate

The Service Worker in the Activated state can handle events such as request interception and cache capture. Until then, we can listen for the Activate event and clean up the old cache files in the callback function.

self.addEventListener("activate", event => {
  const currentCaches = [SHELL, RUNTIME];
  event.waitUntil(
    caches
      .keys()
      .then(cacheNames => {
        returncacheNames.filter( cacheName => ! currentCaches.includes(cacheName) ); }) .then(cachesToDelete => {return Promise.all(
          cachesToDelete.map(cacheToDelete => {
            returncaches.delete(cacheToDelete); })); }) .then(() => self.clients.claim()) ); });Copy the code

What self.clients.claim() does is take control of the page without reloading it.

fetch

The request interception and cache capture step is described below. One of the most attractive aspects of the PWA is the offline capability that this part of the operation implements.

This section covers the two apis mentioned above:

  • Fetch API
  • Cache API

Here’s a simple example.

self.addEventListener('fetch'.function(event) {
  event.respondWith(
    caches.match(event.request)
      .then(function(response) {
        if (response) {
          return response;
        }
        returnfetch(event.request); })); });Copy the code

First we need to listen to the browser’s own FETCH event and respondWith to respond to the page request. The match method of the Catch API is used to find out whether there is a Cache matching the request. If there is no Cache matching the request, the Fetch API is used to make a remote request.

If we had cached the page and associated resources at install, we would have been able to access the page offline at this stage.

This code can be optimized to add the contents of the fetch to the cache when the remote request does not hit the cache, so that the resources can be used directly on the next access.

self.addEventListener("fetch", event => {
  if (event.request.url.startsWith(self.location.origin)) {
    event.respondWith(
      caches.open(RUNTIME).then(function(cache) {
        return cache.match(event.request).then(function(response) {
          var fetchPromise = fetch(event.request).then(function(networkResponse) {
            cache.put(event.request, networkResponse.clone());
            return networkResponse;
          })
          returnresponse || fetchPromise; })})); }});Copy the code

It is worth noting that the response needs to be rendered to the browser and stored in the cache at the same time. Since caches. Put uses the response stream of the file, it is impossible to access the response (understood as destructive read), so it needs to be copied using the Clone method.

Let’s go through the logic of the above code again.

  1. Listen to the browser fetch event, intercept the original request,
  2. Check whether the requested resource exists in the cache. If yes, return to the cache. If no, go to the next step.
  3. Request resources remotely, cache resources and return.

This is a typical “cache first” strategy. In fact, through the sequential combination of the Fetch API and Cache API, multiple strategies can be implemented after intercepting browser Fetch events.

  • The cache is preferred
  • The network is preferred
  • Cache only
  • Network only
  • Speed is preferred

If you are in doubt about the specific implementation of the policy, you can refer to the Service Worker best practices – Tencent Browsing Service, which will not be discussed here.

Redundant

After the new Service Worker enters the Activated state, the old Service Worker becomes redundant.

The Service Worker update

Updating a Service Worker requires only direct changes to the corresponding JavaScript file. The browser automatically detects the difference.

After the new Service Worker has been downloaded and installed, it will enter the waiting state. At this time, two Service workers exist simultaneously, and the old Worker still controls the page. The new Service Worker enters the Activated state and takes over the page only when the old Service Worker stops working.

Web App Manifest

Note that the Manifest here is completely different from the Manifest in the App Cache, which has been removed from the Web standards and replaced by the Service Worker.

JSON ? meta?

The Web App Manifest is basically a file that centrally writes the information and configuration related to a page in the form of JSON. This form of Manifest has been around for a long time in browser plug-in development (perhaps the Manifest in PWA borrows from this form, with different attributes).

The W3C mentions some considerations for the use of an external file in the form of JSON in Manifest. In summary, there are mainly the following points:

  1. Decoupling. There is no need to repeat meta tags on each page for maintenance.
  2. Cacheable. The HTML can change frequently, meaning that the user agent usually needs to download the entire HTML file. Use an external Manifest file to make better use of the cache.
  3. Writing is more flexible. This consideration can be drawn from the comparison between XML and JSON. Labeled structures are good for UI, while structures like JSON are better for data. The Manifest is just some data for the application, and JSON is more appropriate than meta tags in this sense.

usage

Manifest is very simple to use. First you need to refer to it in the head.

<head>
    <link rel="manifest" href="/manifest.json" />
</head>
Copy the code

In the Manifest file, the application information is written in the form of JSON.

{
  "name": "App name"."short_name": "App short name"."description": "Here is the description"."start_url": "."."display": "standalone"."background_color": "#fff"."icons": [{"src": "images/homescreen.png"."sizes": "48x48 72x72 96x96 128x128 256x256"."type": "image/png"
      },
      {
        "src": "icon/logo.ico"."sizes": "96x96"}}]Copy the code

Related Fields

Here are some commonly used fields.

name

The full name of the Web App as a text label for the App icon.

short_name

Give your Web App a short, readable name for use when there is not enough space to display the full name of the application.

description

Describes the Web App.

start_url

Set the URL to load when the user launches the App from the home screen. (When the user adds the App to the first screen on the details page, if the start_URL is empty, the page opened when the user opens the App from the first screen will be the details page.)

scope

Defines a navigational scope for the Context of a Web application, returning a normal Web page if the user browses the application outside the scope.

display

Defines the preferred display mode for the application, which has four optional values, and is currently used by the most popular websites using PWA, standalone.

  • Fullscreen displays in fullscreen without displaying the status bar
  • Standalone looks like a standalone application with different Windows, ICONS, the browser UI that controls navigation will be removed, and may contain other UI elements such as the status bar
  • Minimal-ui acts like a stand-alone application, but includes the browser address bar
  • Browser (default) opens as a traditional browser TAB or as a new window

background_color

Enables the browser to draw the background color of the Web App before the CSS is loaded.

icons

Specifies an array of image objects for the application icon under various circumstances.


In addition, there are other attributes, and you can refer to the MDN documentation or W3C documentation for their usage.

Update the Manifest

Once the user adds an application icon to the desktop, the icon cannot be updated until the user deletes it and then adds it back to the desktop.

Additional considerations

Service Worker Starts performance

In the W3C Github discussion on Service workers, it can be seen that Service workers in Chrome currently take around 200ms to start. This means that the reduced load time of using the Service Worker, if less than 200ms, can actually extend the page load time. This issue is expected to be improved in a subsequent Chrome update this year.

Unable to optimize “first load” speed

As you can see from the process of PWA, PWA does not completely optimize the performance of “first screen loading” (such as white screen). When a new user enters a page after a “first load” or a user clears the browser cache, it takes three network requests to actually use the cache of a file. The first request is for the script file where the Service Worker is located, the second request is for the cached file itself, and on the third request, the cache takes effect. The PWA alone is not enough if you want the user to have a smooth “first load” experience as well.

One of the first ways to optimize the “first load” speed might be to use SSR (Server Side Render) instead of CSR (Client Side Render). Vue even has an official SSR guide on how to use it. Here is to share a presentation by Tencent video front end team — “Extremely Smooth Mobile Web Application Solution”, in which the key rendering paths and related performance of SSR and CSR are compared in detail. As shown in the figure below, which is taken from the presentation PPT, the time saved by SSR compared with CSR mainly comes from the process of JS generating HTML and requesting data to fill the content.

For CSR, there are also optimization measures. For example, you can use the Prerender-SPA-Plugin to generate the First screen of the page at build time during WebPack packaging, or you can significantly reduce FCP (First Contentful Paint) time to optimize the First load.

Domestic PWA ecological environment

In the promotion of PWA technology, Google is more active, and its PWA ecology is relatively complete. But for well-known reasons, Google’s services don’t work in China. For example, In the news push, Google provides FCM service, but there is no relevant alternative infrastructure in China, which makes it difficult to implement this function of PWA in China.

On the other hand, the discussion and experiment of PWA technology are also very active. Perhaps because of its Progressive nature, some of these features are now more widely used. For Service workers, when you open the browser console, you’ll find that familiar product sites like Taobao, QQ Music, and Baidu Web Disk have applied technology to optimize the download time of page resources.

There are differences between browsers

Due to my limited resources and equipment, I only tested the top browsers in iResearch data in July 2018 that can be downloaded and used in the app market.

Description:

  1. Test environment: Android 7.0.0
  2. Test site: Douban
  3. Test criteria: The Service Worker only tests its offline ability (with or without). In the Manifest, due to the lack of uniform performance, Chrome browser has the most function points among them, so It is evaluated from five aspects based on Chrome browser.
  4. Under “Add to Desktop”, “Manual” means to manually add the web page to the desktop by finding the add to desktop entry in the browser; “Prompt” is when the browser prompts the user to add the application to the desktop when entering the page, although the process of confirming the addition still needs to be manually clicked, eliminating the redundant steps of searching for the entry.
  5. “Hide the address bar automatically” refers to the process of clicking from the desktop into the application, and the browser will decide whether to hide the address bar based on the Manifest configuration. Some browsers have other triggers to hide the address bar, but these triggers are related to user actions (such as swiping and sliding) and do not hide the entire address bar.
Browser name Offline capabilities Add to desktop The desktop icon and name are the same as those configured Welcome screen The address bar is automatically hidden Background park is displayed as an application
Chrome (68.0.3440.70) support Prompt + Manual is There are is is
QQ Browser (8.8.0.4420) Does not support manual no There is no no no
UC Browser (12.1.0.990) support manual no There is no no no
360 Browser (8.2.0.128) support Prompt + Manual is There is no no no
Baidu Browser (7.18.20.0) support Prompt + Manual is There is no is is
Samsung Browser (7.2.10.33) support manual is There are is is
Sogou Browser (5.15.15) support manual no There is no no no

As can be seen from the above table, the major domestic browser manufacturers support the offline capability of Service workers very high, perhaps because these browsers are developed based on Chromium kernel. QQ browser because of the use of X5 kernel, performance and Chromium kernel is different. As for Manifest, its function points are probably more a matter of the software implementation itself than of the kernel, and performance varies widely.

summary

Although PWA is not a perfect final solution, and it is still difficult to implement all its features in China, many of its technologies, such as fine control of caching and notification push, have filled in the gaps in the previous Web ecosystem, which is perhaps the most accurate evaluation of it. For me, at least, the idea of “incremental” is enough to make me believe in and look forward to the future of PWA and Web Apps in general. Make Web App great again!

A link to the

PWA website navigation

  • Outweb
  • Appscope

Domestic part PWA

  • douban
  • Alibaba Mobile
  • Mobile version of Weibo
  • Hungry? – H5

tool

  • LightHouse
  • The Manifest validation
  • Mobile device suitability testing
  • OneSignal Message push distribution service
  • Service Worker open source framework – Workbox

Transformation case

  • A Pinterest Progressive Web App Performance Case Study
  • Twitter Lite and High Performance React Progressive Web Apps at Scale
  • More case

reference

  • Your First Progressive Web App
  • App Shell model
  • Web App Manifest
  • PWA-cookbook
  • A brief introduction to the Progressive Web App(PWA)
  • Service Worker API – MDN
  • Service Worker best practices