Webpack代码拆分:ChunkLoadError -加载块X失败,但块存在

bejyjqdl  于 12个月前  发布在  Webpack
关注(0)|答案(3)|浏览(277)

几天前,我将Sentry与我的网站集成在一起,我注意到有时用户会在他们的控制台中收到此错误:

ChunkLoadError: Loading chunk <CHUNK_NAME> failed.
(error: <WEBSITE_PATH>/<CHUNK_NAME>-<CHUNK_HASH>.js)

字符串
因此,我调查了网络上的问题,发现了一些类似的情况,但与会话期间发布更新或缓存问题引起的丢失块有关。
这些情况与我的主要区别在于,失败的块实际上可以从浏览器访问,因此加载错误不取决于发布后块哈希的刷新,而是 (我猜),来自一些网络相关的问题。这个假设被这个统计数据所强化:大约90%的设备涉及移动的

最后,我来问一个问题:我应该以某种方式管理这个问题 (例如,如果失败,重试块加载) 还是直接忽略它,让用户手动刷新更好?

2021.09.28编辑:
一个月后,这个问题仍在发生,但我没有收到任何来自用户的报告,我也不断记录用户与Hotjar的会话,但到目前为止没有发现任何相关的问题。
我最近与Sentry支持人员进行了一次聊天,帮助我排除了网络相关的假设
我们的React SDK默认情况下没有离线缓存,当捕获错误时,它将在此时发送。如果应用无法连接到Sentry发送事件,它将被丢弃,SDK将不会再次尝试发送它。

  • 来自哨兵的鲁道夫 *

我可以确认这个问题是非常不寻常的,我与你分享另一个有趣的统计:自第一次发生以来受影响的用户是32.227独立访问者中的882人(约0,26%),但我注意到90%的事件来自iOS(而不是我一个月前注意到的通用移动的设备),所以如果我计算iOS用户的相同比例,(794(882的90%)出128.444)我们接近0,62%。仍然很小,但肯定更相关的iOS。

r6l8ljro

r6l8ljro1#

块是可访问的并不意味着用户的浏览器可以解析它。例如,如果用户的浏览器是旧的。但是块包含新的语法。
Webpack通过jsonp加载chunk,在<head>中插入<script>标签。如果js chunk文件下载后无法解析,则会抛出ChunkLoadError
你可以按照下面的步骤来复制它。写一个可选的链,不要编译它。确保它输出到一个块。

const obj = {};
obj.sub ??= {};

字符串
通过Chrome 79或Safari 13.0打开您的应用。完整的错误消息如下所示:

SyntaxError: Unexpected token '?'           // 13.js:2
MAX RELOADS REACHED                         // chunk-load-handler.js:24
ChunkLoadError: Loading chunk 13 failed.    // trackConsoleError.js:25
(missing: http://example.com/13.js)

56lgkhnf

56lgkhnf2#

这很可能是因为浏览器缓存了应用的主HTML文件,比如index.html,它提供了webpack包和manifest
首先,我会确保您的Web服务器发送正确的HTTP响应头,以不缓存应用程序的index.html文件(让我们假设它被称为)。如果您使用NGINX,您可以像这样设置适当的头:

location ~* ^.+.html$ {
  add_header Cache-Control "no-store max-age=0";
}

字符串
对于SPA来说,这个文件应该相对较小,所以只要你缓存了应用程序需要的所有其他资产(如JS和CSS),就可以不缓存这个文件,等。你应该在你的JS包上使用内容哈希来支持缓存破坏。有了这个,对你网站的访问应该总是包括最新版本的index.html和最新的资产,包括最新的webpack manifest,它记录了块的名称。
如果你想处理块加载错误,你可以设置如下:

import { ErrorBoundary } from '@sentry/react'

const App = (children) => {
  <ErrorBoundary
    fallback={({ error, resetError }) => {
      if (/ChunkLoadError/.test(error.name)) {
        // If this happens during a release you can show a new version alert
        return <NewVersionAlert />

        // If you are certain the chunk is on your web server or CDN
        // You can try reloading the page, but be careful of recursion
        // In case the chunk really is not available
        if (!localStorage.getItem('chunkErrorPageReloaded')) {
          localStorage.setItem('chunkErrorPageReloaded', true)
          window.location.reload()
        }
      }

      return <ExceptionRedirect resetError={resetError} />
  }}>
    {children}
  </ErrorBoundary>
}


如果你决定重新加载页面,我会提前给用户一条消息。

wtzytmuj

wtzytmuj3#

我也有这样的区块加载问题。我有一个由aspnet 6.0在IIS中托管的angular应用程序。index.htmlcache-controlmax-age=0,区块文件在名称中有哈希值,例如main.4591141fc2c0d492.jscache-control设置为max-age=2592000。当我添加public时,区块加载问题开始(网址://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#public)块文件的指令。问题是不稳定的。通常它工作正常,但有时服务器返回空文件。空文件是一个坏块,所以导致ChunkLoadError。由于这些文件被缓存,问题变得更糟。删除页面并不能解决问题,因为缓存了损坏的(空的)文件。用户必须清理浏览器缓存来解决问题。
删除public缓存指令解决了问题。

相关问题