Webpack代码拆分“加载块失败”错误错误的文件路径

Mar*_*kov 7 typescript reactjs webpack

我在Webpack上使用React + Typescript,我试图在实际需要时加载我的一些React组件。

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

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

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

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

这是一些代码:

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>
        );
    }
}
Run Code Online (Sandbox Code Playgroud)

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"
  ]
}
Run Code Online (Sandbox Code Playgroud)

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"]
    }
};
Run Code Online (Sandbox Code Playgroud)

Chr*_*ras 14

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

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

  • 我过去遇到过这样的问题,今年看到你的问题后我写了这个很晚的答案,让人们知道生成的块文件永远不应该被删除,或者至少在新的块文件构建后保留很长时间。是的,如果你仔细想想,这是有道理的。人们在加载应用程序时将使应用程序与捆绑映射一起运行,因此如果此映射中的某些文件被删除,那么当延迟加载启动并尝试获取它们时,他们将得到 404。 (2认同)

Pla*_*256 8

发生这种情况是因为output.publicPath默认情况下是/

只需更新output.publicPath以指向您想要的位置即可=> /dist/

  • 就我而言,实际上将值设置为“/”解决了问题。我想默认值并不总是“/”。谢谢! (4认同)
  • 当我将脚本存储在 cdn 上时,我不断收到此错误“ChunkLoadError:加载块 'xx' 失败” (3认同)
  • 非常感谢,这为我解决了! (2认同)

小智 5

让我们不要过分关注这一点。它只发生了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();
  }
});
Run Code Online (Sandbox Code Playgroud)

  • 想知道这是否会导致无限循环......猜测可能需要像本地存储计数器之类的东西,因为页面大部分工作可能不需要块 (6认同)
  • 可以确认的是,我们尝试了这个技巧,如果不使用计数器,就会陷入无限循环。 (5认同)