How to overcome loading chunk failed with Angular lazy loaded modules

AngularWebpackCode Splitting

Angular Problem Overview


If I make changes to my angular app the chunk names will change on build and the old version will be removed from the dist folder. Once deployed, if a user is currently on the site, and then navigates to another part of the site, I get a "loading chunk failed" error because the old file is no longer there.

My app is built using Angular CLI and is packaged using webpack.

Is there any way this can be fixed?

Angular Solutions


Solution 1 - Angular

UPDATED SOLUTION BELOW Preferred solution is converting to PWA


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, Injectable} from '@angular/core';

@Injectable()
export class GlobalErrorHandler implements ErrorHandler {
  
  handleError(error: any): void {
   const chunkFailedMessage = /Loading chunk [\d]+ failed/;

    if (chunkFailedMessage.test(error.message)) {
      window.location.reload();
    }
    console.error(error);
  }
}

It is a simple solution and here (Angular Lazy Routes & loading chunk failed) is the article I got it from.


EDIT: Convert to PWA

Another solution can be to convert your Angular site to a PWA (Progressive Web App). What this does is add a service worker that can cache all your chunks. Every time the website is updated a new manifest file is loaded from the backend, if there are newer files, the service worker will fetch all the new chunks and notify the user of the update.

Here is a tutorial on how to convert your current Angular website to a PWA. Notifying the user of new updates is as simple as:

import { Injectable } from '@angular/core';
import { SwUpdate } from '@angular/service-worker';

@Injectable()
export class PwaService {
  constructor(private swUpdate: SwUpdate) {
    swUpdate.available.subscribe(event => {
      if (askUserToUpdate()) {
        window.location.reload();
      }
    });
  }
}

Solution 2 - Angular

You can use custom GlobalErrorHandler in your application, All it does is just check the error message if it has a Loading chunk [XX] failed, and forces the app to reload and load the new fresh chunks.

Create globalErrorHandler with the following code import { ErrorHandler, Injectable } from "@angular/core"; @Injectable() export class GlobalErrorHandler implements ErrorHandler { handleError(error: any): void { const chunkFailedMessage = /Loading chunk [\d]+ failed/; if (chunkFailedMessage.test(error.message)) { if (confirm("New version available. Load New Version?")) { window.location.reload(); } } } }

After creating globalErrorHandler.ts, you should define the ErrorHandler in app.module.ts @NgModule({ providers: [{provide: ErrorHandler, useClass: GlobalErrorHandler}] })

Solution 3 - Angular

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.

Solution 4 - Angular

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.

Solution 5 - Angular

You can also use service workers to detect the change with "polling/intervals" and inform the user for an app update.

https://angular.io/guide/service-worker-getting-started

The service worker can detect every 1minutes for example if there are new "assets/your app" and do a slide up to inform the user to reload the page or even force it if you want to.

Solution 6 - Angular

Good Morning! I had the same problem when assembling the application using angular 11. To solve it, just run as follows.

"ng build --named-chunks"

Solution 7 - Angular

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.

Solution 8 - Angular

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.

Solution 9 - Angular

Clear Browser cache. Worked for me

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiondottodotView Question on Stackoverflow
Solution 1 - AngularLuke KroonView Answer on Stackoverflow
Solution 2 - AngulardevXdView Answer on Stackoverflow
Solution 3 - AngularUlfiusView Answer on Stackoverflow
Solution 4 - AngularterodoxView Answer on Stackoverflow
Solution 5 - AngularJimmy KaneView Answer on Stackoverflow
Solution 6 - AngularLuis GuilhermeView Answer on Stackoverflow
Solution 7 - AngularLovepreet SinghView Answer on Stackoverflow
Solution 8 - AngularDrakeView Answer on Stackoverflow
Solution 9 - AngularjirehView Answer on Stackoverflow