如何解决Create-React-app项目中的Chunk Load错误?

Roy*_* Ra 4 chunks webpack create-react-app webpack-4

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

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

问题是,由于不包含服务器,因此每次部署新文件时,都会创建具有随机哈希值的新块。

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

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

执行后yarn serve,转到正在提供构建文件的相应本地主机。

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

保持浏览器不变,然后重新启动yarn serve,这将提供重命名的块文件。

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

Uncaught SyntaxError: Unexpected token '<'

Loading Chunk n failed.(missing: ~~)
Run Code Online (Sandbox Code Playgroud)

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

+) PS。React.Lazy()我通过在一些代码中使用来实现代码分割。

yol*_*RAC 6

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

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

<meta http-equiv="Pragma" content="no-cache"/>
<meta http-equiv="cache-control" content="no-cache, no-store, must-revalidate"/>
Run Code Online (Sandbox Code Playgroud)

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

其次,使用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;
  }
}
Run Code Online (Sandbox Code Playgroud)

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

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