简体   繁体   English

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

[英]Webpack code splitting: ChunkLoadError - Loading chunk X failed, but the chunk exists

I've integrated Sentry with my website a few days ago and I noticed that sometimes users receive this error in their console:几天前我已将 Sentry 与我的网站集成,我注意到有时用户会在他们的控制台中收到此错误:

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

So I investigated the issue around the web and discovered some similar cases, but related to missing chunks caused by release updates during a session or caching issues.所以我在网上调查了这个问题,发现了一些类似的案例,但与会话期间的发布更新或缓存问题导致的丢失块有关。

The main difference between these cases and mine is that the failed chunks are actually reachable from the browser, so the loading error does not depend on the after-release refresh of the chunk hashes but (I guess) , from some network related issue.这些情况和我的主要区别在于,失败的块实际上可以从浏览器访问,因此加载错误不取决于块哈希的发布后刷新,而是(我猜) ,来自一些网络相关问题。 This assumption is reinforced by this stat: around 90% of the devices involved are mobile .这一统计数据强化了这一假设:大约 90% 的相关设备是移动设备

Finally, I come to the question : Should I manage the issue in some way (eg retrying the chunk loading if failed) or it's better to simply ignore it and let the user refresh manually?最后,我提出了一个问题:我应该以某种方式管理问题(例如,如果失败则重试块加载)还是最好直接忽略它并让用户手动刷新?


2021.09.28 edit: 2021.09.28 编辑:

A month later, the issue is still occurring but I have not received any report from users, also I'm constantly recording user sessions with Hotjar but nothing relevant has been noticed so far.一个月后,问题仍然存在,但我还没有收到用户的任何报告,而且我一直在用 Hotjar 记录用户会话,但到目前为止还没有发现任何相关的问题。

I recently had a chat with Sentry support that helped me excluding the network related hypotesis :我最近与 Sentry 支持进行了一次聊天,帮助我排除了与网络相关的假设

Our React SDK does not have offline cache by default, when an error is captured it will be sent at that point.我们的 React SDK 默认没有离线缓存,当捕获到错误时,它会在那个时候发送。 If the app is not able to connect to Sentry to send the event, it will be discarded and the SDK will no try to send it again.如果应用无法连接到 Sentry 发送事件,该事件将被丢弃,SDK 将不再尝试发送。

Rodolfo from Sentry来自哨兵的鲁道夫

I can confirm that the issue is quite unusual, I share with you another interesting stat: the user affected since the first occurrence are 882 out of 332.227 unique visitors (~0,26%) , but I noticed that the 90% of the occurrences are from iOS (not generic mobile devices as I noticed a month ago), so if I calculate the same proportion with iOS users (794 (90% of 882) out of 128.444) we are near to a 0,62%.我可以确认这个问题很不寻常,我与您分享另一个有趣的统计数据:自第一次出现以来,受影响的用户是 332.227 个独立访问者中的 882 个(~0,26%) ,但我注意到90% 的出现来自 iOS (不是我一个月前注意到的通用移动设备),所以如果我计算与 iOS 用户相同的比例(128.444 中的 794(882 的 90%)),我们接近 0.62%。 Still small but definitely more relevant on iOS.仍然很小,但在 iOS 上肯定更相关。

This is most likely happening because the browser is caching your app's main HTML file, like index.html which serves the webpack bundles and manifest .这很可能会发生,因为浏览器正在缓存您的应用程序的主要 HTML 文件,例如为 webpack 包和清单提供服务的index.html

First I would ensure your web server is sending the correct HTTP response headers to not cache the app's index.html file (let's assume it is called that).首先,我会确保您的 Web 服务器正在发送正确的 HTTP 响应标头,以不缓存应用程序的index.html文件(假设它被称为该文件)。 If you are using NGINX, you can set the appropriate headers like this:如果您使用的是 NGINX,您可以像这样设置适当的标头:

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

This file should be relatively small in size for a SPA, so it is ok to not cache this as long as you are caching all of the other assets the app needs like the JS and CSS, etc. You should be using content hashes on your JS bundles to support cache busting on those.对于 SPA,此文件的大小应该相对较小,因此只要您缓存应用程序所需的所有其他资产(如 JS 和 CSS 等),就可以不缓存它。您应该在您的JS 捆绑包以支持这些缓存破坏。 With this in place visits to your site should always include the latest version of index.html with the latest assets including the latest webpack manifest which records the chunk names.有了这个,对您网站的访问应该始终包含最新版本的index.html和最新资产,包括记录块名称的最新 webpack 清单。

If you want to handle the Chunk Load Errors you could set up something like this:如果要处理块加载错误,可以设置如下:

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

If you do decide to reload the page I would present a message to the user beforehand.如果您决定重新加载页面,我会事先向用户显示一条消息。

The chunk is reachable doesn't mean the user's browser can parse it.块是可访问的并不意味着用户的浏览器可以解析它。 For example, if the user's browser is old.例如,如果用户的浏览器是旧的。 But the chunk contains new syntax.但是该块包含新语法。

Webpack loads the chunk by jsonp. Webpack 通过 jsonp 加载块。 It insert <script> tag into <head> .它将<script>标签插入<head> If the js chunk file is downloaded but cannot parsed.如果js块文件被下载但无法解析。 A ChunkLoadError will be throw.将抛出ChunkLoadError

You can reproduce it by following these steps.您可以按照以下步骤重现它。 Write an optional chain and don't compile it.编写一个可选链,不要编译它。 Ensure it output to a chunk.确保它输出到一个块。

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

Open your app by chrome 79 or safari 13.0.通过 chrome 79 或 safari 13.0 打开您的应用。 The full error message looks like this:完整的错误消息如下所示:

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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Webpack - 加载块 0 失败 - Webpack - Loading chunk 0 failed 如何解决 ChunkLoadError: Loading hot update chunk second_app failed in webpack 5? - How to solve ChunkLoadError: Loading hot update chunk second_app failed in webpack 5? Uncaught SyntaxError: Unexpected token &#39;&lt;&#39; and ChunkLoadError: Loading chunk 16 failed - Uncaught SyntaxError: Unexpected token '<' and ChunkLoadError: Loading chunk 16 failed Fusion Charts Zoomline React 错误:ChunkLoadError:加载块 6 失败 - Fusion Charts Zoomline React Error: ChunkLoadError: Loading chunk 6 failed Vercel Next js Uncaught (in promise) ChunkLoadError: Loading chunk 0 failed - Vercel Next js Uncaught (in promise) ChunkLoadError: Loading chunk 0 failed 使用 Typescript 进行 Cypress 测试中的动态导入:ChunkLoadError:加载块 1 失败 - Dynamic imports in Cypress tests using Typescript: ChunkLoadError: Loading chunk 1 failed Webpack 错误,加载块失败 - Webpack error, Loading chunk failed Angular Uncaught (in promise): ChunkLoadError: Loading chunk XXXfailed - Angular Uncaught (in promise): ChunkLoadError: Loading chunk XXXfailed Laravel Vuejs 未捕获(承诺)ChunkLoadError:加载块博客组件失败 - Laravel Vuejs Uncaught (in promise) ChunkLoadError: Loading chunk blogs-component failed 使用延迟加载/代码拆分处理“加载块失败”错误 - Handle "Loading chunk failed" errors with Lazy-loading/Code-splitting
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM