Angular 2. Error: Loading chunk failed

2020-02-23 08:41发布

问题:

Using angular 2 with lazy loaded modules, I can receive(for example) 401 HTTP code from server

bootstrap 0b40fee…:101 GET http://localhost:8082/2.chunk.js

Error: Loading chunk 2 failed.
at HTMLScriptElement.onScriptComplete (bootstrap 0b40fee…:91)
at HTMLScriptElement.wrapFn (zone.js:1032)
at ZoneDelegate.invokeTask (zone.js:414)
at Object.onInvokeTask (core.es5.js:4119)
at ZoneDelegate.invokeTask (zone.js:413)
at Zone.runTask (zone.js:181)
at HTMLScriptElement.ZoneTask.invoke (zone.js:476)

How to handle this error?

回答1:

I was having the same problem so I investigated. I found the solution. This happened to me when I redeployed to another server and the chunk had a [hash].

You can catch the error either in a catch all like this:

ngOnInit() {
    if (!this.previousRouterErrorHandler) {
        this.previousRouterErrorHandler = this.router.errorHandler;
        let that = this;
        this.router.errorHandler = function (err: any) {
            // Handle here. err.message == "Loading chunk chunk-name failed."

            return that.previousRouterErrorHandler.apply(that.previousRouterErrorHandler, arguments);
        };
    }
}

Or directly at the link which navigated

click() {
    this.router.navigate(['/lazy-route'])
        .catch(err => {
            // Handle here
        });
}


回答2:

Check my answer for details

  • Workaround to bypass this chunk fails error => Programmatically force app to reload if chunks failed error occurs using global error handler.

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();
    }
  }
}
  • Provide it in our root module to change default behavior in our app, so instead of using default ErrorHandler class we are using our custom GlobalErrorHandler class.

@NgModule({   
  providers: [{provide: ErrorHandler, useClass: GlobalErrorHandler}]
})


回答3:

It happen when when deploy new code.The manifest.js which holds the files and hashes doesn't update without refreshing and when it loads a chunk it obviously uses the old hash from manifest.js.

So while catching error we can do force reload with given url :-

click() {
      this.router.navigate(['/lazy-route'])
           .catch(err => {
              // Handle here
              // reload with given route
              // window.location.pathname('/lazy-route');

              // OR
              // reset existing route(containing query params) with given route and force reload
               window.history.pushState({}, document.title, '/lazy-route' );
               window.location.reload();
           });
 }


回答4:

chunk related errors can be raised by any environment or routing related issues making them hard to debunk.

In my case, the amount of data moving in my PWA was too much to handle by the angular router. It was flooding the headers of the js chunks getters and therefore raising bad_request errors.

I suggest you to check out those network calls (getters of chunks.js like http://localhost:xxxx/158.js) for anything unusual in headers and refactor sketchy stuff in your current dev environment, since it's a real black hole time to investigate the source of the error by yourself.

Hope that'll help



回答5:

In my case, I was putting my files in an S3 bucket. I kept getting this error because it was calling the wrong filenames all together and returning an html error response.

At some point I let the IT team know what was happening. They were like, let's invalidate the cache on CloudFront... What?! Yeah! Let's do that...

Moral of the story, if you've been searching the web for answers to this error and can't find any, check with the IT team or any place that the index.html file might be getting cached.



回答6:

this probably means unhandled exception. you have to handle error responses (4xx, 5xx status codes) from server in whatever way you want: show error message somewhere, redirect to some page, do anything but not leave it unhandled.

for example:

return this.http.get(requestDetails)
          .map(res => res.json())
          .catch(err => {
console.log('server error:', err)
Observable.throw(err);
});