The foreword 0.
We all know that PWA is a new technology. It can run normally offline and turn on in seconds, relying on caching. I migrated the original game to React, then to Webpack + React, and finally to PWA. I won’t go into details, but let’s get started.
1.webpack
There are many webpack walkthrough, without further ado, a brief introduction to some key points. Remember a few points: entry, output, plug-in plugins, module loader. Your next complete project should contain at least this.
There is also a path module, specifically read the path, do all the configuration, the path first do well:
// This is how we usually do it
var path = require("path");
var ROOT_PATH = path.resolve(__dirname);// The current main entry directory
var SRC_PATH = path.resolve(ROOT_PATH,"src");// SRC, the code you wrote is here
var DIST_PATH = path.resolve(ROOT_PATH,"dist");// Package the result
var COMP_PATH = path.resolve(SRC_PATH,"component");// React has both components
// Then our configuration inside
var config = {
mode:'development'.entry: path.resolve(__dirname, './src/index.js'),// Webpack turns the main entry HTML into JS, and then injects the HTML
output:{
path:DIST_PATH,
filename:"bundle.js"}},Copy the code
Module loaders, normally we do not use the preprocessor, continue to add configuration in config, this way basically meet the needs
module: {rules:[
{
test:/\.(es6|js)$/.// Take es6 into account
use:[
{
loader:"babel-loader",}],exclude:/node_modules/ // Do not take nodemodules into account
},
{
test:/\.(css)$/.use:[
{
loader:"style-loader"
},
{
loader:"css-loader"}].exclude:/node_modules/
},
{
test:/\.(png|jpeg|jpg|gif)$/.use:[
{
loader:"url-loader",}],exclude:/node_modules/}}]Copy the code
For plugins, htmlWebpackPlugin and hot updates are usually enough
plugins:[
new webpack.HotModuleReplacementPlugin(),
new htmlWebpackPlugin({
title: 'game'.template: path.resolve(__dirname, './index.html'),
//bunld.js will be injected into it
inject: true
}),
new OfflinePlugin() // This is used by PWA, which will be covered later
]
Copy the code
There is also a server:
var server = new WebpackDevServer(webpack(config), {
contentBase: path.resolve(__dirname, './dist'), // The local server is provided as a root folder by default, specifying the folder here
historyApiFallback: true.// This is the history route. If set to true, all jumps will point to index.html
port: 9090./ / the default 8080
publicPath: "/".// The directory where the page is loaded by the local server
hot: true./ / hot update
inline: true.// Refresh in real time
historyApiFallback: true / / don't jump
});
server.listen(9090.'localhost'.function (err) {
if (err) throw err
})
Copy the code
Oh, and list the require manifest and package.json:
var webpack = require("webpack");
var path = require("path");
var htmlWebpackPlugin = require("html-webpack-plugin");
var webpackDelPlugin = require("webpack-del-plugin");
var WebpackDevServer = require('webpack-dev-server');
var ROOT_PATH = path.resolve(__dirname);
var SRC_PATH = path.resolve(ROOT_PATH,"src");
var DIST_PATH = path.resolve(ROOT_PATH,"dist");
var TEM_PATH = path.resolve(SRC_PATH,"component");
var OfflinePlugin = require('offline-plugin')
//package.json
{
"name": "pwawebpack"."version": "1.0.0"."main": "index.js"."license": "MIT"."dependencies": {
"jquery": "^ 3.3.1"."react-scripts": 1.1.1 ""
},
"devDependencies": {
"babel-core": "^ 6.26.3"."babel-loader": "^" 7.1.4."babel-plugin-react-transform": "^ 3.0.0"."babel-preset-es2015": "^ 6.24.1"."babel-preset-react": "^ 6.24.1"."babel-preset-react-hmre": "^ 1.1.1"."css-loader": "^ 0.28.11"."file-loader": "^ 1.1.11"."html-webpack-plugin": "^ 3.2.0"."offline-plugin": "^ 5.0.3." "."react": "^ 16.3.2"."react-dom": "^ 16.3.2"."react-transform-hmr": "^" 1.0.4."style-loader": "^ 0.21.0"."url-loader": "^" 1.0.1."webpack": "^ 4.8.3"."webpack-cli": "^ 2.1.3"."webpack-del-plugin": "Hundreds"."webpack-dev-server": "^ 3.1.4." "."webpack-notifier": "^ 1.6.0." "
},
"scripts": {
"dev": "webpack-dev-server --inline --progress --config webpack.config.js"}}Copy the code
In order to quickly see the effects of pWA +webpack, we will not write ESLint and test
2.pwa
Let’s take the examples from Baidu. A normal PWA consists of index.html, a CSS, a manifest.json, and a sw.js. We’re going to start a PWA, which is a must. Actually, doesn’t it look a bit like an extension to Chrome? Have you ever tried writing your own Chrome add-ons for Google, such as adblocking, personal tools, favorites to certain websites, etc. After all, it looks a bit like a family.
html:
<head>
<title>PWA</title>
<meta name="viewport" content="width=device-width, user-scalable=no" />
<link rel="stylesheet" type="text/css" href="main.css">
</head>
<body>
<h1>1</h1>
</body>
Copy the code
Manifest.json: This is basically the same browser extension you wrote yourself, with name, style, logo configuration
{
"name": "PWA"."short_name": "p"."display": "standalone"."start_url": "/"."theme_color": "#0000ff"."background_color": "#00ff00"."icons": [{"src": "logo.png"."sizes": "256x256"."type": "image/png"}}]Copy the code
The lifecycle of the software includes Parsed, Installed, Activated, and Redundant failover. If it fails, it jumps to the Redundant phase. Then we listen for these events and see what happens.
var cacheStorageKey = 'v1'
var cacheList = [
'/'."index.html"."main.css"."logo.png"
]
self.addEventListener('install', e => {
e.waitUntil(
caches.open(cacheStorageKey)
.then(cache= > cache.addAll(cacheList))
.then((a)= > self.skipWaiting())
)
})
self.addEventListener('fetch'.function(e) {
e.respondWith(
caches.match(e.request).then(function(response) {
if(response ! =null) {
return response
}
return fetch(e.request.url)
})
)
})
self.addEventListener('activate'.function(e) {
e.waitUntil(
Promise.all(
caches.keys().then(cacheNames= > {
return cacheNames.filter(name= >name ! == cacheStorageKey ).map(name= >caches.delete(name))
})
).then((a)= > {
return self.clients.claim()
})
)
})
Copy the code
Note that pWA requires HTTPS or localhost, because it can pull all your local files, which can do other things, so it has to be safe to run. Also, is it found that the HTML, JS files changed, empty the cache does not update it? In fact, you can change the sw, manifest application cache is also, change the version number, or add a space on the line.
3. Webpack-based PWA
Documentation is available on the official website.
We can run without configuration, but there are some things that need to be paid attention to in the configuration and can not be arbitrarily changed, see the documentation. Common Settings are: Caches (default to all cache, or set yourself), externals (array form, means other resources such as CDN), excludes (array form, except what can’t be cached), autoUpdate (how long does it take to update, defaults to one hour)
We use offline-plugin. We just need to introduce it directly in the plugin:
plugins: [
/ /... Other plug-ins
new OfflinePlugin()
]
Copy the code
Then add to our entry file index.js:
import * as OfflinePluginRuntime from 'offline-plugin/runtime';
OfflinePluginRuntime.install();
Copy the code
Try offline mode for Google Chrome and you’ll find it still works: