我有一个单页应用程序,可以在每条路由上进行代码拆分.当我部署我的应用程序的新版本时,如果用户仍然打开页面并访问了他们以前从未访问过的路由,那么用户通常会收到一个错误.

另一种可能发生这种情况的情况是,如果应用程序启用了服务工作者.当用户在新部署后访问页面时,服务人员将从缓存中提供服务.然后,如果用户试图访问不在其缓存中的页面,则会导致区块加载失败.

目前,我在应用程序中禁用了代码拆分,以避免出现这种情况,但我一直很好奇,处理这个问题的最佳方法是什么.我考虑过在用户完成加载初始页面后预加载所有其他路由,我相信这可能会解决路由上的代码拆分问题.但假设我想在组件上进行代码拆分,那就意味着我必须设法弄清楚何时以及如何预加载所有这些组件.

所以我想知道人们如何处理单页应用的这个问题?谢谢(我目前正在使用create react应用程序)

推荐答案

I prefer to let the user refresh rather than refreshing automatically (this prevents the potential for an infinite refresh loop bug).
The following strategy works well for a React app, code split on routes:

策略

  1. 设置索引.html永远不会缓存.这可以确保请求初始assets资源 的主文件始终是新的(通常它不太大,所以不缓存它不应该是一个问题).见MDN Cache Control.

  2. 对块使用一致的块哈希.这确保了只有更改的块才会有不同的散列.(请参阅下面的webpack.config.js片段)

  3. 不要在部署时使CDN的缓存失效,这样旧版本在部署新版本时不会丢失其块.

  4. 在路由之间导航时,请判断应用程序版本,以便通知用户它们是否在旧版本上运行,并请求刷新.

  5. 最后,万一发生ChunkLoadError does:添加一个错误边界.(参见下面的错误边界)

来自网页包的片段.配置.js(网页包v4)

Uday Hiwarale开始:

optimization: {
  moduleIds: 'hashed',
  splitChunks: {
      cacheGroups: {
          default: false,
          vendors: false,
          // vendor chunk
          vendor: {
              name: 'vendor',
              // async + async chunks
              chunks: 'all',
              // import file path containing node_modules
              test: /node_modules/,
              priority: 20
          },
      }
  }

误差边界

React Docs for 误差边界

import React, { Component } from 'react'

export default class ErrorBoundary extends Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError(error) {
    // Update state so the next render will show the fallback UI.    
    return { hasError: true, error };
  }
  componentDidCatch(error, errorInfo) {
    // You can also log the error to an error reporting service    
    console.error('误差边界 Caught:', error, errorInfo);
  }
render() {
    const {error, hasError} = this.state
    if (hasError) {
      // You can render any custom fallback UI      
      return <div>
      <div>
        {error.name === 'ChunkLoadError' ?
          <div>
            This application has been updated, please refresh your browser to see the latest content.
          </div>
          :
          <div>
            An error has occurred, please refresh and try again.
          </div>}
      </div>
      </div>
    }
    return this.props.children;
  }
}

注意:确保清除内部导航事件上的错误(例如,如果您使用react router),否则错误边界将持续超过内部导航,并且仅在真正的导航或页面刷新时消失.

Reactjs相关问答推荐

For循环中的元素在Reaction中丢失挂钩

如何在MUI X数据网格列中显示IMG?

TypeError:SearchProduct.get()获得了意外的关键字参数查询'

导致useState中断的中断模式

NextJS如何正确保存添加到购物车中的产品会话

Reaction中的数据加载不一致

这两个子元素在Reaction Native中使用的有什么不同?

GitHub页面未正确显示Reaction应用程序网站

使用Next.js和Next-intl重写区域设置

列表中的每个子项都应该有一个唯一的keyprops .在react 应用程序中

我如何使用 React toastify (Promise) toast 和邮箱 js

Next.js `getLayout` 函数没有被调用

如何更新 FunctionComponentElement 的 props

React - 如何重定向页面以显示数据修改?

如何初始化 redux 全局存储 preloadedState

自动重新获取不起作用 - RTK 查询

setState 改变对象引用

如何从一组对象映射 MUI 5 图标并更改其 colored颜色 ?

在react 路由dom版本6中的组件内添加路由

react 路由:router.ts:11 没有匹配的路由位置/管理