0. Предисловие
Мы все знаем, что pwa — это новая технология, основанная на кеше, она может нормально работать в автономном режиме и открываться за считанные секунды. Я мигрировал небольшие игры, которые написал изначально, чтобы реагировать, затем мигрировал на webpack+react и, наконец, обновился до pwa. Без дальнейших церемоний, давайте начнем.
1.webpack
Стратегий webpack очень много, так что не будем вдаваться в подробности, просто кратко представим некоторые ключевые моменты. Запомните несколько моментов: вход-вход, выход-выход, подключаемые плагины, загрузчик модулей, загрузчик. Далее, соответствующие операции вашего полного проекта должны включать по крайней мере эти.
Существует путь перед модулем, посвященным пути к чтению, выполните всю конфигурацию, первая, кто сделает хороший правильный путь:
//一般我们就是这样子做的
var path = require("path");
var ROOT_PATH = path.resolve(__dirname);//当前主入口目录
var SRC_PATH = path.resolve(ROOT_PATH,"src");//src,你写的代码在这里
var DIST_PATH = path.resolve(ROOT_PATH,"dist");//打包结果
var COMP_PATH = path.resolve(SRC_PATH,"component");//vue、react都有的component
//然后我们的配置里面
var config = {
mode:'development',
entry: path.resolve(__dirname, './src/index.js'),//webpack把主入口html变成js,然后注入html
output:{
path:DIST_PATH,
filename:"bundle.js"
},
}
Загрузчик модулей В общем, если нам не нужен препроцессор, мы продолжаем добавлять конфигурацию в конфиг, что в принципе соответствует требованиям.
module:{
rules:[
{
test:/\.(es6|js)$/,//考虑到es6
use:[
{
loader:"babel-loader",
}
],
exclude:/node_modules/ //不把nodemodules考虑进去
},
{
test:/\.(css)$/,
use:[
{
loader:"style-loader"
},
{
loader:"css-loader"
}
],
exclude:/node_modules/
},
{
test:/\.(png|jpeg|jpg|gif)$/,
use:[
{
loader:"url-loader",
}
],
exclude:/node_modules/
}
]
}
Для плагинов мы обычно используем htmlWebpackPlugin и горячие обновления.
plugins:[
new webpack.HotModuleReplacementPlugin(),
new htmlWebpackPlugin({
title: 'game',
template: path.resolve(__dirname, './index.html'),
//bunld.js会注入里面
inject: true
}),
new OfflinePlugin() //这是pwa用的,等下讲到
]
Так же есть сервер:
var server = new WebpackDevServer(webpack(config), {
contentBase: path.resolve(__dirname, './dist'), //默认会以根文件夹提供本地服务器,这里指定文件夹
historyApiFallback: true, //这是history路由,如果设置为true,所有的跳转将指向index.html
port: 9090, //默认8080
publicPath: "/", //本地服务器所加载的页面所在的目录
hot: true, //热更新
inline: true, //实时刷新
historyApiFallback: true //不跳转
});
server.listen(9090, 'localhost', function (err) {
if (err) throw err
})
Да, кстати, перечислите требуемый список и 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": "0.0.2",
"webpack-dev-server": "^3.1.4",
"webpack-notifier": "^1.6.0"
},
"scripts": {
"dev": "webpack-dev-server --inline --progress --config webpack.config.js"
}
}
Чтобы быстро увидеть эффект от pwa+webpack, мы не будем писать eslint и тестировать
2.pwa
Возьмем примеры из Baidu: обычный pwa состоит из index.html, css, manifest.json и sw.js. Мы собираемся начать pwa, что является обязательным. На самом деле, разве это не похоже на расширение Google Chrome? Вы когда-нибудь пытались написать свои собственные плагины для браузера Google, такие как плагины для блокировки рекламы, личные инструменты, определенные избранные веб-сайты и т. д.? В конце концов, это семья, так что это выглядит немного похоже.
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>
manifest.json: По сути, это расширение для браузера, написанное вами, это некоторая конфигурация с названием, стилем и логотипом.
{
"name": "PWA",
"short_name": "p",
"display": "standalone",
"start_url": "/",
"theme_color": "#0000ff",
"background_color": "#00ff00",
"icons": [
{
"src": "logo.png",
"sizes": "256x256",
"type": "image/png"
}
]
}
конкретное введение ПОкликните сюдаЖизненный цикл, потом не говорите, несколько этапов: анализ анализа, установка установлена, активирована активирована, среднее не подпрыгивает непосредственно к резервной стадии отходов, а затем мы слушаем эти события, мы видим прямой эффект.
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(() => 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(() => {
return self.clients.claim()
})
)
})
Обратите внимание, что PWA требует https или localhost, потому что эта штука может вытащить все ваши локальные файлы, и это может также сделать другие вещи, поэтому он должен работать в безопасных условиях. Кроме того, вы обнаружите, что файлы HTML и JS были изменены, и кеш был очищен без обновления? На самом деле, вы можете изменить SW, а манифест также используется в качестве кеша приложения. Просто измените номер версии или добавьте пространство.
3. PWA на основе веб-пакета
Документацию см.Официальный сайт
Мы можем запустить его без конфигурации, но в конфигурации есть некоторые места, которые необходимо обратить внимание и не может быть изменено произвольно. Прочитайте документацию самостоятельно. Обычно используемые конфигурации: кэширует (все кэшируется по умолчанию, или вы можете установить его самостоятельно), внешние (в форме массива, указывающие другие ресурсы, такие как CDN), исключая (в форме массива, за исключением того, какие из них не может быть кэшировать), autooupdate Сколько времени после обновления по умолчанию составляет один час))
Мы используем плагин offline-plugin, нам нужно только импортировать его прямо в плагин:
plugins: [
// ... 其他插件
new OfflinePlugin()
]
Затем присоединяемся к нашему входному файлу index.js:
import * as OfflinePluginRuntime from 'offline-plugin/runtime';
OfflinePluginRuntime.install();
Можно запускать веб-пакет напрямую таким образом. Попробуйте автономный режим Google Chrome, и вы обнаружите, что по-прежнему можете запускать: