If I make changes to my angular app the chunk names will change on build and the old version will be remove from the dist folder. Once deployed if a user is currently on the site and then navigated to another part of the site I get a loading chunk failed error as the old file is no longer there.
My app is built using angular cli so it's packaged using webpack.
Is there anyway this can be overcome.
I keep my old chunks in place for a couple days after an update for just this purpose. My app also consists of mini-SPAs, so as they move around, they're likely to pick up the new version during a page load.
I had the same problem and found a pretty neat solution that is not mentioned in the other answers.
You use global error handling and force app to reload if chunks failed.
import { ErrorHandler } from '@angular/core';
@Injectable()
export class GlobalErrorHandler implements ErrorHandler {
handleError(error: any): void {
const chunkFailedMessage = /Loading chunk [\d]+ failed/;
if (chunkFailedMessage.test(err.message)) {
window.location.reload();
}
}
}
It is a simple solution and here (Angular Lazy Routes & loading chunk failed) is the article I got it from.
I know I'm a little late to the game on this questions, but I would recommend changing your deployment approach.
Check out https://immutablewebapps.org/. The basic philosophy is to isolate you build time assets from your runtime variables. This provides a bunch of benefits, but the biggest are:
- No caching problems for assets because they are isolated at the route level
- The same code that was vetted in development is used in production
- Instant fallback with hot cache for consumers in the case of a problem
- Chunks that are created are maintained for previous version isolated by routes avoiding the active deployment vs active user problem
This also should not interfere with the ** PreloadAllModules** suggestion offered by @dottodot below.
Disable the hashing of chunks
ng build --output-hashing none
For more information see the official build documentation
You can send some event from server side to reload the application. Also there is option to pre fetch the lazy modules in background so as to prefetch them as soon as possible instead of waiting for the request of that modules.
Use Pre-Loading. You get the benefits of lazy loading, without the hassle it causes in situations like this. All of the chunks will be given to the user as fast as possible without slowing down the initial load time. Below is an excerpt from https://vsavkin.com/angular-router-preloading-modules-ba3c75e424cb to explain how it works (see the article for diagrams):
First, we load the initial bundle, which contains only the components
we have to have to bootstrap our application. So it is as fast as it
can be.
Then, we bootstrap the application using this small bundle.
At this point the application is running, so the user can start
interacting with it. While she is doing it, we, in the background,
preload other modules.
Finally, when she clicks on a link going to a lazy-loadable module,
the navigation is instant.
We got the best of both worlds: the initial load time is as small as
it can be, and subsequent navigations are instant.
Clear Browser cache. Worked for me