The app is using react and React Route-based code splitting: 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.
Uncaught SyntaxError: Unexpected token <
How can I prevent that and show for example: "Site has been updated, please reload" instead of a white page?
Solution is:
Did you know that the import(...) function that we use on lazy is just a function that returns a Promise? Which basically means that you can chain it just like any other 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. If even after 5 tries it import it, then an error is thrown.
Thanks to Guilherme Oenning from: https://dev.to/goenning/how-to-retry-when-react-lazy-fails-mb5