I encountered a bug last year that was a bit tricky because it wasn't something that we would ever run into during development but was a legitimate problem in production. I found the bug because I set up Sentry for our client application and it was reporting that there were unhandled exceptions being thrown with the name ChunkLoadError. It would happen consistently in production but rarely, if ever, in the master and stage environments.
Because of the name, I immediately understood that this was probably being thrown by the client-side Webpack logic which was failing to load a "page" in our application. Pages are split into separate bundles (also known as chunks) so that users only need to download them when they navigate to a route for that individual page.
At first we thought that the error was caused by mobile users with spotty cell service. The thinking was that a user would try to navigate to a new page, the request would fail because of a weak or interrupted connection, Webpack would throw the error when the request failed, and Sentry would store and report the error when the connection had been re-established. This assumption turned out to be incorrect and lulled us into a false sense of security that the error wasn't one we could fix.
A little later on we enabled the Release Tracking feature in Sentry which allowed us to correlate exceptions to individual releases and I noticed that the the error reports seemed to cluster around new releases.
By trying to replicate a simplified production release locally, I was able to figure out that the problem was one we could fix. The error occurred because each chunk's filename contains a hash based on it's content so that if the content changes, the application would be able to retrieve the updated chunk instead of using the old one stored in the browser's cache.
The manifest of chunk filenames that the application uses is only loaded on a full page load so if a user navigates to the application, we release a new version with updated pages, and, without doing a full page load, the user tries to navigate to one of those pages, the client application will try to request the old chunk filename contained in the manifest. At the time, we weren't using a CDN and instead serving static files directly from the server so requests for the old chunks would fail since they didn't exist within the application server's filesystem.
Using a CDN prevented the error from being thrown since the old chunks would still be cached for a certain period of time, but it didn't solve the core issue since users that were using our application during a new release would still be using the old client application as long as they kept the browser tab open.
I solved this issue by adding a try-catch around the navigation and page import logic so that if a page chunk request fails, the app will do a full page request via window.location
instead of just a request for the individual chunk.
Top comments (7)
We've also experienced this issue. I wondered why I'd not really experienced this kind of thing before. Usually it's because the site is behind CloudFlare which handles this at CDN level for me.
So I figure the easiest thing to do is just to get nginx to act more like a CDN and ask the browser to hold on to the js/css files for longer.
This is my proposed solution:
This will tell the browser to cache the files for 2 hours, hopefully by that time, the browser will have refreshed the page and got the new files.
Another idea might be to use a service worker to tell the client that there's a new version of the files and hard refresh.
Hope this helps someone to look at the problem in a slightly different way.
Hi Ian. Thanks for this post! We're running into the same issue and also have Sentry. What's interesting is that if I try to follow the chunk URL in the Sentry issues, they resolve correctly. We're using Next.js and by default it doesn't remove old build artifacts when we deploy a new build.
I'm facing the same issue. I can also access the old chunks that failed to load. Were you able to figure this out in the end?
Thanks!
Hi, could you please elaborate on how you do a page request via window.location?
window.location = "https://google.com"
Thanks! I was getting the same error here and was trying to figure this out. I am glad I tried googling it before diving into the code. haha!
Hello, a question: I can't find a solution different from the usual ones of avoiding caching. I'm developing a micro-frontend, and it's causing problems in the production environment. Do you have any updates?