【问题标题】:Webpack Code Splitting 'Loading chunk failed' error wrong file pathWebpack Code Splitting 'Loading chunk failed' 错误文件路径错误
【发布时间】:2019-05-11 07:27:33
【问题描述】:

我正在将 React + Typescript 与 Webpack 一起使用,并且我正在尝试在实际需要时加载一些我的 react 组件。

问题是当通过延迟加载请求块时,我收到以下错误:

未捕获的错误:加载块 1 失败。 (错误:http://localhost:58988/1.chunk.js) 在 HTMLScriptElement.onScriptComplete (bootstrap:114)

这个chunk生成成功,没有任何错误,只是路径不对-http://localhost:58988/1.chunk.js应该是http://localhost:58988/dist/1.chunk.js

我也尝试使用最新的 React.lazy 来延迟加载反应组件,但我遇到了同样的问题。那么,有没有办法告诉编译器如何解析这些文件路径呢?

以下是部分代码:

MyComponent.tsx

import * as React from "react";
import * as ES5Promise from "promise";

export class MyComponent extends React.Component<{}, {}> {
    constructor(props) {
        super(props);
    }

    private readonly onLoadModuleClickHandler = (): void => {
        import("./Button").then((module) => {
            console.log(module);
        });
    }

    render() {
        return (
            <div>
                <input type="button" value="Load another module" onClick={this.onLoadModuleClickHandler}/>
            </div>
        );
    }
}

tsconfig.json

{
  "compilerOptions": {
    "moduleResolution": "node",
    "noImplicitAny": false,
    "noEmitOnError": true,
    "module": "esnext",
    "removeComments": false,
    "sourceMap": false,
    "target": "es5",
    "jsx": "react",
    "noEmit": true,
    "importHelpers": true,
    "lib": ["dom", "es5", "es2015.promise"]
  },
  "exclude": [
    "node_modules",
    "wwwroot"
  ]
}

webpack.config.js

module.exports = {
    entry: {
        "app": "./src/App.tsx"
    },
    output: {
        path: path.resolve(__dirname, 'wwwroot/dist'),
        filename: "[name].bundle.js",
        chunkFilename: "[name].chunk.js"
    },
    module: {
        rules: [
            {
                test: /\.(ts|tsx)?$/,
                use: "awesome-typescript-loader",
                exclude: /node_modules/
            },
            {
                test: /\.(css|less)?$/,
                use: [{
                    loader: "style-loader"
                }, {
                    loader: "css-loader?modules&localIdentName=[local]--[hash:base64:5]"
                }, {
                    loader: "less-loader"
                }]
            },
        ]
    },
    resolve: {
        extensions: [".js", ".jsx", ".ts", ".tsx", ".css", ".less"]
    }
};

【问题讨论】:

    标签: reactjs typescript webpack


    【解决方案1】:

    另一个选项可以简单地使用Magic Comment /* webpackMode: "eager" */ 我们希望动态加载的地方。显然它不会获取丢失的块,而是从包中获取。

    它确实超出了分块的目的,但它解决了问题。

    【讨论】:

      【解决方案2】:

      webpack.config.jsoutput.publicPath 的值设置为/ 将解决问题。

      【讨论】:

        【解决方案3】:

        在我的情况下,window.addEventListener('error'... 没有触发,所以我重写了console.error 方法,如下所示:

            const origin = console.error;
            console.error = (error) => {
              if (/Loading chunk [\d]+ failed/.test(error.message)) {
                alert('A new version released. Need to relaod the page to apply changes.')
                window.location.reload();
              } else {
                origin(error);
              }
            }
        

        【讨论】:

          【解决方案4】:

          我们不要过分关注这一点。它只发生了5次。我相信有人打开 excalidraw 有一段时间了,我们在此期间推送了一个新版本,当他们回来时,他们尝试加载一些惰性块,但它不再存在。

          我们在 Facebook 解决此问题的方法是,我们将 CDN 上的先前块保留一周,如果捆绑包超过一周,我们会强制为人们刷新应用程序。这样我们就不需要关心非常旧的版本了。

          以上回复来自vjeux

          我的计划是监听window.onerror中的错误,然后提示用户刷新浏览器。

          window.addEventListener('error', e => {
            // prompt user to confirm refresh
            if (/Loading chunk [\d]+ failed/.test(e.message)) {
              window.location.reload();
            }
          });
          

          【讨论】:

          • 想知道这是否会导致无限循环......猜测可能需要像本地存储计数器或其他东西,因为页面大部分工作可能不需要块
          • 可以确认,我们尝试了这个技巧,如果你不使用计数器,我们就会陷入无限循环。
          【解决方案5】:

          重新部署时,在重新构建应用程序包时,请确保 NOT 用以前的块文件清理输出文件夹,因为已经加载应用程序的用户将尝试获取以前不存在的块文件没有了。

          最好的办法是跟踪应用版本(使用 AJAX 并从数据库或动态配置文件中读取),当应用检测到更新版本时,向用户发送消息并询问他们重新加载页面。

          【讨论】:

          • +1 这有点晚了,但我仍然记得当我真正让这些块工作时,我在尝试延迟加载组件时经常会收到 404 错误,所以最终我选择不使用这种延迟加载东西。当我现在阅读您的评论时,它实际上很有意义。
          • 我过去遇到过这样的问题,今年看到你的问题后我写了这个很晚的答案,让人们知道生成的块文件永远不应该被删除,或者至少要保留在构建新的块文件后很长时间。是的,如果你仔细想想,这是有道理的。人们在加载应用程序时将使用捆绑地图运行应用程序,因此如果此地图中的某些文件被删除,那么当延迟加载启动并尝试获取它们时,他们将得到 404。
          【解决方案6】:

          这是因为output.publicPath 默认为/

          只需将output.publicPath 更新到您想要的位置 => /dist/

          【讨论】:

          • 非常感谢,这已经帮我解决了!
          • 在我的情况下,实际上将值设置为/ 解决了问题。我猜默认值并不总是/。谢谢!
          • 当我将脚本存储在 cdn 上时,我不断收到此错误,ChunkLoadError: Loading chunk 'xx' failed
          • 这确实需要在拆分块文档中,因为正如@icl7126 所说,默认情况下这并不总是/,可能会造成混淆。
          猜你喜欢
          • 2019-07-30
          • 2023-03-03
          • 1970-01-01
          • 2018-09-10
          • 2021-09-27
          • 2021-04-27
          • 2020-07-20
          • 2020-03-24
          • 2016-09-02
          相关资源
          最近更新 更多