We are using Suspense and route based code splitting with react 16. This uses Webpack chunks to split the code into smaller bits for different routes in the application. In production mode this produces chunks with a hash named something like 7.8817be1b.chunk.js.
The issue is that when we deploy a new production release users with the app open who client side navigate to a page requiring a new chunk get an error (they have the old bundle, so they are requesting an old no-longer existing chunk).
We are not too sure how to deal with this error, does react have any guidance around what we should do with existing users who are requesting old chunks? Can some guidance about this be added to the docs: https://reactjs.org/docs/code-splitting.html
React: 16.12.0
This doesn't seem like a React issue per se, it would happen with any bundler that makes chunks based on dynamic imports (like webpack, etc). How you deal with it depends on the user experience you'd prefer. For example, you don't have to delete older chunks from your cdn/wherever you're serving scripts from, so the older scripts still load (you'd have to be careful that any APIs serving this app before the deploy still work). Alternately, you could detect that a deploy has 'happened', and pop up a message on the site asking the user to refresh their page (I've seen google news and a couple of other sites do this).
Thanks for your suggestions, keeping old copies in the cdn sounds like a sensible way forward for us.
The reason I think this is a react issue is that there is a whole section in the documentation around code splitting (and features in react to support it too). This problem seems like it would be one that anyone who is using code splitting would face, so it seems like the react docs should provide some explicit guidance.
We try to use this issue tracker for bug reports and feature requests for React only. While this may be an issue you encounter following the official guidance on the React website, it doesn't mean that it's a problem with React itself. As @threepointone said, this is a problem that occurs with bundling and code-splitting in general. I recommend checking out the list of great support resources listed on the doc page, Where to Get Support.
Find a solution to retry loading the component. seem to work
function retry(
fn: () => Promise<{
default: React.ComponentType<any>;
}>,
retriesLeft = 100,
interval = 1000
) {
return new Promise<{
default: React.ComponentType<any>;
}>((resolve, reject) => {
fn()
.then(resolve)
.catch((error: any) => {
setTimeout(() => {
if (retriesLeft === 1) {
reject(error);
return;
}
retry(fn, interval, retriesLeft - 1).then(resolve, reject);
}, interval);
});
});
}
component: lazy(() => retry(() => import("./pages/dashboard/Dashboard"))),
Find a solution to retry loading the component. seem to work
function retry( fn: () => Promise<{ default: React.ComponentType<any>; }>, retriesLeft = 100, interval = 1000 ) { return new Promise<{ default: React.ComponentType<any>; }>((resolve, reject) => { fn() .then(resolve) .catch((error: any) => { setTimeout(() => { if (retriesLeft === 1) { reject(error); return; } retry(fn, interval, retriesLeft - 1).then(resolve, reject); }, interval); }); }); }
component: lazy(() => retry(() => import("./pages/dashboard/Dashboard"))),
I'm trying this solution out, thanks!
It looks like
retry(fn, interval, retriesLeft - 1).then(resolve, reject);
should be...
retry(fn, retriesLeft - 1, interval).then(resolve, reject);
though.
Most helpful comment
Thanks for your suggestions, keeping old copies in the cdn sounds like a sensible way forward for us.
The reason I think this is a react issue is that there is a whole section in the documentation around code splitting (and features in react to support it too). This problem seems like it would be one that anyone who is using code splitting would face, so it seems like the react docs should provide some explicit guidance.