reactjs - 代码分割导致 SPA 新部署后无法加载 block

标签 reactjs webpack single-page-application webpack-2 create-react-app

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

另一种可能发生这种情况的情况是应用程序启用了服务工作人员。当用户访问新部署后的页面时,Service Worker 将从缓存中提供服务。然后,如果用户尝试访问不在缓存中的页面,他们将遇到 block 加载失败的情况。

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

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

最佳答案

我更喜欢让用户刷新而不是自动刷新(这可以防止出现无限刷新循环错误的可能性)。
以下策略适用于 React 应用程序,在路由上拆分代码:

策略

  1. 将您的index.html 设置为从不缓存。这可以确保请求初始资源的主文件始终是最新的(通常它并不大,因此不缓存它应该不是问题)。请参阅MDN Cache Control .

  2. 对 block 使用一致的 block 散列。这确保了只有发生变化的 block 才会具有不同的哈希值。 (请参阅下面的 webpack.config.js 片段)

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

  4. 在路线之间导航时检查应用版本,以便通知用户是否在旧版本上运行并请求刷新。

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

来自 webpack.config.js 的片段(Webpack 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 Error Boundary

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('Error Boundary 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 路由器),否则错误边界将持续经过内部导航,并且只会在真正的导航或页面刷新时消失.

关于reactjs - 代码分割导致 SPA 新部署后无法加载 block ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44601121/

相关文章:

reactjs - 如何以编程方式 react 焦点输入

webpack - Vue js 和 scss 或 Sass

javascript - 如何解决我的 TypeScript/ESLint/Webpack 转译问题

javascript - React.js 中 componentWillMount 调用的顺序

css - 如何在单页 MEAN 堆栈应用程序中使用 addy osmani 的 uncss

javascript - 单页应用程序和网页标题

reactjs - 如何在 React 中使用动画 Material ui 图标

rest - 我无法通过 React 调用休息电话

javascript - React + Express + Nodemailer : Can't render components and Nodemailer together

Webpack copy-webpack-plugin 运行得太早