代码拆分导致新部署SPA后无法加载块 [英] Code splitting causes chunks to fail to load after new deployment for SPA

查看:71
本文介绍了代码拆分导致新部署SPA后无法加载块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a single page app that I code split on each route. When I deploy a new version of my app the users will usually get an error if a user still has the page open and visits a route they haven't visited before.

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

Another scenario where this can also happen is if the app has service workers enabled. When the user visits a page after a new deployment, the service worker will serve from the cache. Then if the user tries to visit a page not in their cache, they'll get the chunk loading failure.

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

Currently I disabled code splitting in my app to avoid this but I've been very curious what's the best way to handle this issue. I've thought about pre-loading all the other routes after the user finishes loading the initial page and I believe this might fix the issue for code splitting on routes. But let's say I want to code split on components then that would mean I have to try to figure out when and how to pre-load all of those components.

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

So I'm wondering how do people handle this issue for single page apps? Thanks! (I'm currently using create-react-app)

推荐答案

我更喜欢让用户刷新而不是自动刷新(这避免了无限刷新循环错误的可能性).
以下策略对于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. 将index.html设置为从不缓存.这样可以确保请求您的初始资产的主文件始终是新文件(并且通常不大,因此不进行缓存不应该成为问题).请参见 MDN缓存控制.

对块使用一致的块哈希.这样可以确保只有更改的块才会具有不同的哈希.(请参见下面的webpack.config.js代码段)

Use consistent chunk hashing for your chunks. This ensures that only the chunks that change will have a different hash. (See webpack.config.js snippet below)

在部署时不要使CDN的缓存无效,因此在部署新版本时,旧版本不会丢失其块.

Don't invalidate the cache of your CDN on deploy so the old version won't lose it's chunks when a new version is deployed.

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

Check the app version when navigating between routes in order to notify the user if they are running on an old version and request that they refresh.

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

Finally, just in case a ChunkLoadError does occur: add an Error Boundary. (See Error Boundary below)

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
          },
      }
  }

错误边界

对文档进行错误边界

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-router),否则错误边界将在内部导航之后持续存在,并且仅在实际导航或页面刷新时才会消失

Note: Make sure to clear the error on an internal navigation event (for example if you're using react-router) or else the error boundary will persist past internal navigation and will only go away on a real navigation or page refresh.

这篇关于代码拆分导致新部署SPA后无法加载块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆