【问题标题】:How to solve Chunk Load Error in Create-React-app project?如何解决 Create-React-app 项目中的块加载错误?
【发布时间】:2021-08-05 08:29:05
【问题描述】:

我正在部署一个使用 CRA(Create-React-App) 生成的项目,并且所有 babel 和 webpack 配置保持不变。

另外,我正在使用 AWS S3 的静态存储桶托管功能部署我的 React 应用程序。

问题是,由于没有包含服务器,每次部署新文件时,都会创建具有随机散列的新块。

当客户端在旧哈希的网站中,并且部署了新哈希时,客户端会收到块加载错误。

为了演示这一点,使用 yarn build 构建项目并转到 /build 文件夹以查看 webpack 生成的块。然后使用serve,我可以演示我的部署将如何在我的本地机器上运行。

yarn serve 被执行后,转到相应的 localhost 来提供构建文件。

然后,在/build/static/js 文件夹中,根据需要重命名每个块文件的哈希值。

不要理会浏览器,然后重新启动yarn serve,它将提供重命名的块文件。

然后回到浏览器,你很可能会得到两个错误:

Uncaught SyntaxError: Unexpected token '<'

Loading Chunk n failed.(missing: ~~)

我认为可以解决这个问题的方法是在发生 ChunkLoadError 时重新加载网页。遗憾的是,window.reload(boolean) 函数已被弃用,仅使用 window.location.reload() 并不能解决此问题。

+) PS。我在一些代码中使用React.Lazy() 实现了代码拆分。

【问题讨论】:

    标签: webpack create-react-app webpack-4 chunks


    【解决方案1】:

    您提出的解决方案必须有效:

    您所要做的就是将这 2 个元标记添加到您的 index.html 中:

    <meta http-equiv="Pragma" content="no-cache"/>
    <meta http-equiv="cache-control" content="no-cache, no-store, must-revalidate"/>

    这将阻止浏览器在刷新页面时使用缓存

    其次,使用react的ErrorBoundary组件来放置你的刷新逻辑

    例如:

    import React from "react";
    
    const PageHasBeenForceRefreshed = "page-has-been-force-refreshed";
    
    const retryPageLoading = () => {
      const pageHasAlreadyBeenForceRefreshed = JSON.parse(
        window.localStorage.getItem(PageHasBeenForceRefreshed) || "false"
      ) as boolean;
    
      if (!pageHasAlreadyBeenForceRefreshed) {
        window.localStorage.setItem(PageHasBeenForceRefreshed, "true");
        return window.location.reload();
      } else {
        window.localStorage.setItem(PageHasBeenForceRefreshed, "false");
      }
    };
    
    interface ErrorBoundaryProps {
      children: React.ReactNode;
    }
    export class ErrorBoundary extends React.Component<ErrorBoundaryProps, { hasError: boolean }> {
      constructor(props: Readonly<ErrorBoundaryProps>) {
        super(props);
        this.state = { hasError: false };
      }
      componentDidCatch(error: unknown, info: unknown) {
        retryPageLoading();
        this.setState({ hasError: true });
        console.log(error, info);
      }
      render() {
        if (this.state.hasError) {
          return <>Your error component</>;
        }
        return this.props.children;
      }
    }

    当 index.html 中缺少一个块时,错误边界将捕获错误并运行函数“retryPageLoading()”。 函数“retryPageLoading()”使用本地存储来避免无限循环。当发生错误并且页面没有刷新是时,通过“window.location.reload()”完成刷新

    最后,将你的 React 应用包装在 ErrorBoundary 中,以便在块丢失时捕获块错误

    import * as React from "react";
    import { ErrorBoundary } from "./components/ErrorBoundary/ErrorBoundary";
    
    const App: React.FunctionComponent = () => {
      return <ErrorBoundary>Your app</ErrorBoundary>;
    };

    告诉我它是否有效。祝你好运

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-28
      • 2018-05-02
      • 1970-01-01
      • 1970-01-01
      • 2021-12-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多