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
- 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).
- 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.
- Listen to the browser fetch event, intercept the original request,
- Check whether the requested resource exists in the cache. If yes, return to the cache. If no, go to the next step.
- 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:
- Decoupling. There is no need to repeat meta tags on each page for maintenance.
- 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.
- 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:
- Test environment: Android 7.0.0
- Test site: Douban
- 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.
- 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.
- “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