Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to overcome loading chunk failed with Angular lazy loaded modules

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?

like image 863
dottodot Avatar asked Mar 09 '18 16:03

dottodot


2 Answers

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();     }   } } 

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();       }     });   } } 
like image 101
Luke Kroon Avatar answered Sep 22 '22 12:09

Luke Kroon


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}] }) 
like image 32
devXd Avatar answered Sep 22 '22 12:09

devXd