背景:h5应用每次发布之后会有部分用户白屏
React v5
render() {
if(this.state.loading) {
return <PendingPage />
}
return (
<Router>
<Suspense fallback={<PendingPage />}>
{
this.state.showPage ?
<Switch>
{routes.map((route, i) => (
<RouteWithSubRoutes key={i} {...route} />
))}
</Switch>
: <PendingPage />
}
</Suspense>
</Router>
);
}
const path = require("path");
const fs = require("fs");
// 将当前时间戳写入json文件
let json_obj = { build_version: new Date().getTime().toString(),status:200,success:true };
fs.writeFile(
path.resolve(__dirname, "./public/json/build_version.json"),
JSON.stringify(json_obj),
function(err) {
if (err) {
return console.error(err);
}
console.log("打包字符串写入文件:public/json/build_version.json,成功!");
}
);
// "build": "node create_build_version_json.js && react-app-rewired build",
// 写入package.json 打包先执行次node.js
增加react路由守卫,在每次切换页面去请求生成的时间戳
// FrontendAuth.js
import React, { Component } from "react";
import { Route, Redirect } from "react-router-dom";
import axios from "axios";
class FrontendAuth extends Component {
constructor(props) {
super(props);
}
render() {
const { routerConfig, location } = this.props;
const { pathname } = location;
axios.get("/json/build_version.json?v=" + new Date().getTime().toString()).then(res=>{
let newBuildStr = res.data.build_version;
let oldBuildStr = localStorage.getItem("build_version") || "";
if (oldBuildStr !== newBuildStr) {
localStorage.setItem("build_version", newBuildStr);
window.location.reload();
}
})
const targetRouterConfig = routerConfig.find(
(item) => item.path === pathname
);
if (targetRouterConfig) {
const { component } = targetRouterConfig;
return <Route exact path={pathname} component={component} />;
}
}
}
export default FrontendAuth;
// app.jsx
render() {
return (
<Router>
<Suspense fallback={<PendingPage />}>
<Switch>
<FrontendAuth routerConfig={routerMap} />
</Switch>
</Suspense>
</Router>
);
}
// router/routerMap.js-路由集合
const Index= React.lazy(() => import('../pages/index/index.jsx'));
export default [
{
path: '/index',
component: Index,
}
]
config.output.filename = 'static/js/[name].[contenthash].js?_v=[contenthash]'
config.output.chunkFilename = 'static/js/[name].[contenthash].chunk.js?_v=[contenthash]'
// 某些浏览器可能会忽略.js?v=xxxx
#对html文件限制缓存
location ~ .*\.(html)$ {
add_header Cache-Control no-store;
add_header Pragma no-cache;
}
<meta
http-equiv="cache-control"
content="no-cache,no-store, must-revalidate"
/>
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Cache" content="no-cache" />
注: 目前灰度方案由前端cookie控制,但是必须要先全量发布之后才能走灰度,灰度方案不支持。
根据自己的情况。
componentDidCatch(error, info) {
if (String(error).includes('Loading chunk')) {
// 解决灰度切换js缺失的问题
window.location.reload();
} else {
// 容错机制-会导致所有的报错回到此页面-再考虑一下!
// window.location.replace('/404')
}
}