PWA
申请项目ID
访问PWA离线平台,选择新项目接入,填入项目名称新建项目,找到刚刚新建的项目,获取项目ID。
安装依赖
// npm
引入插件
feflow.js中引入插件
const PWAPlusPlugin = require('');
const config = {
plugins: [
new PWAPlusPlugin({
dev: process.env.NODE_ENV === 'development',
swDest: 'sw.js',
pid: id,
web: '//demo.qq.com/',
cdn: '//s.url.cn/demo/a/b/',
})
]
}
注册Service worker
在脚手架中,base-pwa中已经配置该项,但是需要对id进行修改
import { Workbox } from 'r'
const wb = new Workbox('./sw.js', { scope: './', id: id })
wb.register()
并且在RootComponents中进行初始化PWA
import pwa from '/business/base-pwa';
// sw
pwa.init();
添加配置文件
增加灰度配置文件 在根目录下增加灰度配置文件pwa_config.json,此处如果修改名字,则需要在script脚本命令修改对应的文件名
// pwa_config.json
{
"id": ,
"is_gray": true,
"gray_uins": "12asdasdaszxczxczx,1145",
"gray_regex": "/^[1-9][0-9]{4,10}$/"
}
启动项目后如果service work成功启动并能请求deRequest,则接入成功
Package.json创建脚本
{
"scripts": {
"pwa-publish": "pwap publish -m dist/pwa-manifest.json -c pwa_config.json"
}
}
在.orange-ci.yml中添加,既可以在OCI构建完成之后自动上传更新。
- name: pwa-plus publish
script: npm run pwa-publish
本地开发
本地开发需要增加额外的代理
检查service work的状态
如果配置成功,那么会在application中的Service Workers中看到activited and is running,并且在Catch一栏中看到对应id的catch
点击catch中id的catch可以看到缓存的资源
即配置成功
pwa+直出
在pwa+直出的环境中出现了一个问题就是有时候Application中Service Workers的域名每刷新一次就会增加一个,而且属性还是is redundant(废弃)
它是Service Workers生命周期的最终态
Service Workers的生命周期
生命周期可以分为两个阶段:1.安装过程。2.激活过程。
installing状态
当注册一个新的Service Worker时,浏览器进行下载脚本解析,这个时候Service Worker处于installing状态,如果下载成功,就会进入installed状态,如果下载失败就会进入redundant状态。
installed(waiting)状态
ServiceWorker成功安装后便进入installed
状态。这个时候Service完成了安装过程
,等待接管页面已有的worker,从而可以控制页面。
activating状态
ServiceWoker安装成功后进入activating
状态。
activated状态
这时ServiceWorker可以进行控制页面,监听功能事件了,例如fetch,push事件。默认情况下ServiceWorker只能控制在其激活成功后才加载完成的页面。
redundant状态
redundant
状态是ServiceWorker的最终态,进入该状态的情况:
- register安装失败,如果多次安装register,后调用注册的SW会变成redundant
- 安装失败
- 被新版本的Service Workers替换
解决方式
为了避免这种情况,需要再进行配置一个 fetch
函数
在RootComponent.tsx中的componentDidMount生命周期中添加如下代码
if (window.isIsomorphism && window.__initialState) {
// 从sw中更新数据
this.fetchFromSW();
}
fetchFromSW = () => {
// PWA+SSR 方案,从 sw 中获取数据更新 state
pwa.queryState().then((state) => {
console.log('[goodsorder.html] PWA_FRESH_STATE');
aegis.info('PWA_FRESH_STATE');
this.props.dispatch({
type: 'PWA_FRESH_STATE',
data: state,
});
});
};
所以还需要在store.js中添加相应的type
interface PWAFreshAction {
type: 'PWA_FRESH_STATE';
data: any;
}
/** 这里加了个 global type 做 pwa fresh */
export default (state: AppState, action: AppActions): AppState => {
if (action.type === 'PWA_FRESH_STATE') {
// console.log(action);
// console.log(action.data);
return action.data;
}
return baseRootReducer(state, action);
};