When talking about PWA, many people may still only stay at the level of “understanding” and have not really tried it in practice. More often, they have only probably tried online tutorials and examples. However, the examples on the network are mostly simple demo, rarely combined with real development, such as the engineering combination with webpack. This article will start with a webpack plugin and talk about how to use this web pack plugin calledoffline-plugin
PWA is easily implemented by the webpack plug-in of.
Since there are too many articles related to PWA, this article will not repeat the basic contents such as “what is PWA” and “PWA’s life cycle”.
offline-plugin
Related links:
I. Automatic Generationservice-worker.js
The core of PWA isservice-worker
(hereinafter referred to as SW), any PWA has and only has oneservice-worker.js
The file is used to add a resource list for SW and perform life cycle operations such as registration and activation. However, in a project built with a webpack, aservice-worker.js
There may be two big problems:
- 1. Most of the resources generated by the webpack will generate a string of hash. sw’s resource list needs to update these resources with hash synchronously.
- 2. Every time the code is updated, the client needs to be notified to update the cached resources by updating the sw file version number. (In fact, as long as the sw code this time is different from the previous sw code, the update can be triggered, but it is more appropriate to use a clear version number).
Seeing this, you may have thought, has the universal webpack community provided the corresponding plugin to help us handle these things automatically? The answer is yes. In addition to the official recommendationsw-precache-webpack-pluginIn addition, there are our main characters today.offline-plugin.
Compared withsw-precache-webpack-pluginIn my opinionoffline-pluginHas the following advantages:
- 1. More optional configuration items to meet more detailed configuration requirements;
- 2. More detailed documents and examples;
- 3. The update frequency is relatively higher and the number of star is more.
- 4, automatically processing the life cycle, and users do not need to struggle with the pit of the life cycle;
- *5. AppCache; is supported;
- 6. Automatic Generation
manifest
Documents. - …
II. Basic Use
Installation
npm install offline-plugin [--save-dev]
Initialization
Step one, enterwebpack.config
:
// webpack.config.js example
var OfflinePlugin = require('offline-plugin');
module.exports = {
// ...
plugins: [
// ... other plugins
// it's always better if OfflinePlugin is the last plugin added
new OfflinePlugin()
]
// ...
}
The second step, theruntime
Add to your portal js file:
require('offline-plugin/runtime').install();
ES6/Babel/TypeScript
import * as OfflinePluginRuntime from 'offline-plugin/runtime';
OfflinePluginRuntime.install();
After the above steps,offline-plugin
It has been integrated into the project and can be built through a webpack.
III. Configuration
As I said earlier,offline-plugin
Support detailed configuration to meet different needs. The following will introduce several commonly used configuration items for your further use.
-
Tell the plug-in what to cache and how to cache it. `all': means that all resources built by the webpack, as well as those in the externals' option, will be cached. `Object`: Contains three arrays or regular configuration Object (main`, `additional`, `optional), which are optional and are empty by default. Default: `all'.
-
Allows developers to specify some external resources (such as CDN references or resources not generated through webpack) . The function of caching external resources can be realized by matching the' additional' item of the' Caches'. Default: null' For example: ` ['fonts/roboto.woff'] `
-
ServiceWorker: Object | null | false
This object contains multiple configuration items, only the most commonly used are listed here. Events': boolean value. Allows the runtime to accept messages from sw with a default of false. NavigateFallbackURL': When a URL request cannot be obtained from the cache or the network, it will be redirected to the URL pointed to by this option.
-
AppCache: Object | null | false
"offline-plugin" supports "AppCache" by default, but the "AppCache" draft has been abandoned by web standards and is not recommended. However, because some browsers still support it, the plug-in provides this function by default.
IV. runtime
The previous section describedoffline-plugin
For the configuration in the webpack, this section will introduce some usage of the runtime.
To makeoffline-plugin
To take effect, the user must initialize in the entry js file through the runtime:
//via AMD
require('offline-plugin/runtime').install();
//or through ES6/Babel/TypeScript
import * as OfflinePluginRuntime from 'offline-plugin/runtime';
OfflinePluginRuntime.install();
OfflinePluginRuntime
Object provides the following three methods:
-
install(options: Object)
Open the installation process of ServiceWorker/AppCache. This method is secure and must be called when the page is initialized. In addition, please do not put it in any conditional statement. (This sentence is not entirely correct, and will be described in detail in the following downgrade plan.) -
applyUpdate()
Accept the update information of sw currently installed. -
update()
Check the update information of the new version of ServiceWorker/AppCache.
runtime.install()
The method accepts a configuration object parameter that is used to process events in each life cycle of sw:
-
When ServiceWorker/AppCache is install, it can be used to show that "APP already supports offline access."
-
AppCache does not support this method. Triggered when update information is obtained and the browser is updating resources. At this moment, some resources are being downloaded.
-
Triggered when the' onUpdating' event completes. At this time, all resources have been downloaded. Runtime.applyUpdate ()' method to trigger the update.
-
Triggered when the' onUpdating' event fails for some reason. At this time, no resources are downloaded and all resource update processes should be canceled or skipped.
-
Triggered when the update is accepted.
V. downgrade plan
When we need to remove sw for demotion at certain times, we need to actively cancel sw. However,offline-plugin
By default, there is no provision for logging off sw.unregister()
Method, so we need to implement it ourselves.
In fact, it is very simple to log off sw voluntarily, we can call it directlyServiceWorkerContainer.getRegistrations()
How to get itregistration
Instance, and then call theregistration.unregister()
Method, the specific code is as follows:
if ('serviceWorker' in navigator) {
navigator.serviceWorker.getRegistration().then((registration) => {
registration && registration.unregister().then((boolean) => {
boolean ? Alert ('Logout Successful'): alert ('Logout Failed')
});
})
}
After calling this method, sw has been logged off, refresh the page to see that the resources are retrieved from the network again.
In a real production environment, we can decide whether to use a downgrade scheme by calling the interface:
fetch(URL).then((switch) => {
if (switch) {
OfflinePluginRuntime.install()
} else {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.getRegistration().then((registration) => {
registration && registration.unregister().then((boolean) => {
boolean ? Alert ('Logout Successful'): alert ('Logout Failed')
})
})
}
}
})
VI. Pits Encountered
In the specific practice, encountered a relatively large pit, issw.js
Update of files.
In the design of service worker, every time the browser loads the URL of the site, it will request it again.sw.js
. If found this timesw.js
If the content is different from the previous one, it will be judged as resource update and the sw life cycle will be re-triggered. However,sw.js
It is also a common js resource file, which will use the expired time set by the server by default, that is, itsmax-age
. After understanding the design of service worker, we can easily find that,sw.js
Themax-age
It should be as short as possible so that the browser can update the resource list in time.
This is also my direct use in the research phase.http-server
In the past few days. Later in the official example, I found thatnpm script
It reads as follows:
"start": "http-server ./dist -p 7474 -c no-cache"
It is worth our attention to directly specify that all resources do not use cache.
In addition,webpack-dev-server
It cannot be used normally.offline-plugin
Because it requires specific files to generatesw.js
But throughwebpack-dev-server
The files of the built project are stored in memory, so they cannot be compared withoffline-plugin
It is normally used together. It is recommended thatProduction modeInternal useoffline-plugin
.
Seven, add to the main screen
Mobile browsers all provide the function of “adding to the home screen”, but ordinary websites add to the home screen only by putting the bookmarks of the websites on the desktop. If you want to add the website to the main screen as PWA, we need oneJson file:
{
"name": "offline-plugin",
"icons": [
{
"src": "/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"theme_color": "#181743",
"background_color": "#181743",
"start_url": "/",
"display": "standalone"
}
Then, take thismanifest.json
And otherStatic resourcesPack them in the root directory of the website:
Sample address:
Open chrome Developer Tool and enterApplication
One column, selectManifest
, you can see the effect:
ByCurrently (15 August 2017), what I useiOS10.3.2The version of iPhone7 already supports PWA, with the following effects:
After consulting a large amount of data, so far, iOS does not support PWA, but it can add several tags in html to achieve similar experience effects of web pages and native APP:
Apply icon:
<link rel="apple-touch-icon" href=“/custom_icon.png">
Startup screen:
<link rel="apple-touch-startup-image" href="/launch.png">
Application name:
<meta name="apple-mobile-web-app-title" content="AppTitle">
Full screen effect:
<meta name="apple-mobile-web-app-capable" content="yes">
Set the status bar color:
<meta name="apple-mobile-web-app-status-bar-style" content="black">
Open with safari
Open after adding to main screen
Open from home screen after offline
Open task manager
It can be seen that PWA exists as an independent APP in terms of performance and function.
Viii. conclusion
Originally, I always thought Apple did not support PWA well, but through this practice, we can know that PWA has made great progress and developers can build their own PWA happily.
The conclusion cannot be drawn too early. . .