使用基于 React Route 的代码拆分进行全新构建后的白页

White page after fresh build using React Route-based code splitting

该应用正在使用 React 和基于 React Route 的代码拆分:https://reactjs.org/docs/code-splitting.html#route-based-code-splitting

该应用运行良好。一个用户在主页上。 然后我更改代码并重新构建应用程序。

用户正在单击 link,他正登陆一个白色页面。 当然,bundle 已经改变,加载新页面(感谢React.lazy)会报错。

Uncaught SyntaxError: Unexpected token <

如何防止这种情况并显示例如:"Site has been updated, please reload" 而不是白页?

解决方法是:

你知道我们在 lazy 上使用的 import(...) 函数只是一个 returns Promise 的函数吗?这基本上意味着您可以像任何其他 Promise 一样链接它。

function retry(fn, retriesLeft = 5, interval = 1000) {
  return new Promise((resolve, reject) => {
    fn()
      .then(resolve)
      .catch((error) => {
        setTimeout(() => {
          if (retriesLeft === 1) {
            // reject('maximum retries exceeded');
            reject(error);
            return;
          }

          // Passing on "reject" is the important part
          retry(fn, retriesLeft - 1, interval).then(resolve, reject);
        }, interval);
      });
  });
}

现在我们只需要将它应用到我们的惰性导入中。

// Code split without retry login
const ProductList = lazy(() => import("./path/to/productlist"));

// Code split with retry login
const ProductList = lazy(() => retry(() => import("./path/to/productlist")));

如果浏览器无法下载模块,它将重试 5 次,每次尝试之间有 1 秒的延迟。如果即使在 5 次尝试导入它之后,也会抛出错误。

感谢 Guilherme Oenning 来自:https://dev.to/goenning/how-to-retry-when-react-lazy-fails-mb5

这是根据 Alan 的评论构建的,它并没有完全解决原始问题的问题。我遇到了一个类似的问题,在服务器上完成的构建更改了我使用 React.lazy() 加载的捆绑包的所有文件名,并且没有刷新页面的用户将寻找不再存在的捆绑包,导致他描述的错误。

同样,这主要基于 Alan 的代码,但很好地解决了问题...

export default function lazyReloadOnFail(fn) {
  return new Promise(resolve => {
    fn()
      .then(resolve)
      .catch(() => {
        window.location.reload();
      });
  });
}


const Report = React.lazy(() => lazyReloadOnFail(() => import('./views/Reports/Report')));