react h5 发版白屏问题解决方案

背景:h5应用每次发布之后会有部分用户白屏
React v5

1. 优化路由加载时间 app.jsx
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>
    );
  }
2. 自刷新模式build_version-react路由
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,
    }
]
3. webpack打包 生成的js版本号_v=hash值(config-overrides.js)
config.output.filename = 'static/js/[name].[contenthash].js?_v=[contenthash]'
config.output.chunkFilename = 'static/js/[name].[contenthash].chunk.js?_v=[contenthash]'
// 某些浏览器可能会忽略.js?v=xxxx
4. ng配置不缓存html(已存在)
#对html文件限制缓存        
location ~ .*\.(html)$ {            
    add_header Cache-Control no-store;
    add_header Pragma no-cache;        
}
5. 前端html header(index.html)(已存在)
<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" />
6. 灰度发布 / 服务器增加一台灰度服务器,运维控制流量切换服务器,着步切换

注: 目前灰度方案由前端cookie控制,但是必须要先全量发布之后才能走灰度,灰度方案不支持。
根据自己的情况。

7. 新增js报错监控,如果检测到js报错,跳转空页面。手动点击登录。(app.jsx)
componentDidCatch(error, info) {
    if (String(error).includes('Loading chunk')) {
      // 解决灰度切换js缺失的问题
        window.location.reload();
    } else {
      // 容错机制-会导致所有的报错回到此页面-再考虑一下!
      // window.location.replace('/404')
    }
  }

你可能感兴趣的:(react.js,javascript,前端)