简体   繁体   English

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

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

The app is using react and React Route-based code splitting: https://reactjs.org/docs/code-splitting.html#route-based-code-splitting该应用程序正在使用基于 React 和 React 路由的代码拆分: https : //reactjs.org/docs/code-splitting.html#route-based-code-splitting

The app is working fine.该应用程序运行良好。 A user is on the homepage.一个用户在主页上。 Then I do a change in the code and build the app again.然后我更改代码并再次构建应用程序。

User is clicking on a link, and he is landing on a white page.用户点击一个链接,他正在登陆一个白页。 Of course, the bundle has changed, and loading the new page (thanks to React.lazy ) will drop an error.当然,bundle 发生了变化,加载新页面(感谢React.lazy )会React.lazy一个错误。

在此处输入图片说明 Uncaught SyntaxError: Unexpected token <

How can I prevent that and show for example: "Site has been updated, please reload" instead of a white page?如何防止这种情况并显示例如:“网站已更新,请重新加载”而不是白页?

This is built off Alan's comment, which doesn't quite solve the problem of the original question.这是建立在艾伦的评论之上的,它并没有完全解决原始问题的问题。 I faced a similar issue where a build done on a server changed all the file names of the bundles I was loading using React.lazy() and a user who didn't refresh their page would be looking for bundles that no longer exists, resulting in the error he describes.我遇到了一个类似的问题,在服务器上完成的构建更改了我使用 React.lazy() 加载的包的所有文件名,并且没有刷新页面的用户将寻找不再存在的包,结果在他描述的错误中。

Again, this is mostly based off Alan's code but solves the problem nicely...同样,这主要基于 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')));

Solution is:解决办法是:

Did you know that the import(...) function that we use on lazy is just a function that returns a Promise?你知道我们在 lazy 上使用的 import(...) 函数只是一个返回 Promise 的函数吗? Which basically means that you can chain it just like any other 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);
      });
  });
}

Now we just need to apply it to our lazy import.现在我们只需要将它应用于我们的惰性导入。

// 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")));

If the browser fails to download the module, it'll try again 5 times with a 1 second delay between each attempt.如果浏览器无法下载模块,它将重试 5 次,每次尝试之间有 1 秒的延迟。 If even after 5 tries it import it, then an error is thrown.如果即使在 5 次尝试后导入它,也会引发错误。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM