Webpack程式码分割“载入区块失败”错误,档案路径错误

6tdlim6h  于 2022-11-13  发布在  Webpack
关注(0)|答案(9)|浏览(198)

我正在使用React + Typescript和Webpack,我试图在实际需要的时候加载一些react组件。
问题是,当通过延迟加载请求块时,我会收到以下错误:
未捕获的错误:载入区块1失败。(错误:(引导程序:114)。
此区块已成功生成,没有任何错误,只是路径错误-http://localhost:58988/1.chunk.js,而它应该是http://localhost:58988/dist/1.chunk.js
我也尝试过使用最新的React.lazy来延迟加载React组件,但是我也遇到了同样的问题。那么,有没有办法告诉编译器如何解析这些文件路径呢?

以下是部分代码:
我的组件.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>
        );
    }
}

文件系统配置.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"
  ]
}

网页包.配置.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"]
    }
};
aydmsdu9

aydmsdu91#

这是因为output.publicPath默认为/
只需将output.publicPath更新到您希望的位置=〉/dist/

jdzmm42g

jdzmm42g2#

重新部署时,在重建应用程序捆绑包时,请确保不要清理包含以前的块文件的输出文件夹,因为已加载应用程序的用户将尝试获取不再存在的以前的块文件。
最好的办法是有一个应用程序版本跟踪(* 使用 AJAX 和从数据库或动态配置文件读取 *),当应用程序检测到一个较新的版本,消息用户,并要求他们重新加载页面。

gkl3eglg

gkl3eglg3#

让我们不要过于关注这个问题。它只发生了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();
  }
});
dfuffjeb

dfuffjeb4#

在我的例子中,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);
      }
    }
uz75evzq

uz75evzq5#

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

8zzbczxx

8zzbczxx6#

另一个选项可以简单地使用Magic Comment /* webpackMode:“eager”*/我们希望动态加载的地方。显然,它不获取丢失的块,而是从包中获取。
它确实击败了组块的目的摆在首位,但它解决了问题。

e4eetjau

e4eetjau7#

我解决这个问题的方法是将webpack配置中的output.publicPath设置为auto
https://webpack.js.org/guides/public-path/#automatic-publicpath

xyhw6mcr

xyhw6mcr8#

你可以试着清空缓存,因为你的浏览器可能没有下载数据块,而是使用了缓存版本的应用程序。

c2e8gylq

c2e8gylq9#

当你在React.lazy中使用代码拆分时,有时会出现“chunk load error loading chunk 4 failed in react”错误。如果你刷新页面,错误就会消失。如果你按照以下步骤操作,你就不需要手动刷新了。
如果您在app.js中使用以下代码导入页面,则不会发生此错误

const lazyRetry = function(componentImport) {

    return new Promise((resolve, reject) => {
 
  const hasRefreshed = JSON.parse(
      window.sessionStorage.getItem('retry-lazy-refreshed') || 'false'
  );
 
  componentImport().then((component) => {
      window.sessionStorage.setItem('retry-lazy-refreshed', 'false');
      resolve(component);
  }).catch((error) => {
      if (!hasRefreshed) { // not been refreshed yet
          window.sessionStorage.setItem('retry-lazy-refreshed', 'true');
          return window.location.reload(); // refresh the page
      }
      reject(error); 
  });
 });
};

将页面导入为

const YourPage = React.lazy(()=> lazyRetry(() => import('./pages/YourPage')))

相关问题