使用Angular延迟加载模块如何克服加载块失败

时间:2018-03-09 16:37:23

标签: angular webpack code-splitting

如果我对我的角度应用程序进行了更改,则块名称将在构建时更改,旧版本将从dist文件夹中删除。一旦部署用户当前在网站上,然后导航到网站的另一部分,我就会收到加载块失败错误,因为旧文件不再存在。

我的应用程序是使用angular cli构建的,因此它使用webpack打包。

无论如何,这可以克服。

9 个答案:

答案 0 :(得分:2)

您可以在应用程序中使用自定义 GlobalErrorHandler,它所做的只是检查错误消息是否有加载块 [XX] 失败,并强制应用程序重新加载并加载新的块。< /p>

使用以下代码创建globalErrorHandler

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

创建globalErrorHandler.ts后,您应该在ErrorHandler

中定义app.module.ts
@NgModule({
  providers: [{provide: ErrorHandler, useClass: GlobalErrorHandler}]
})

答案 1 :(得分:1)

出于这个目的,我在更新后将旧数据块保留了几天。我的应用程序还包含微型SPA,因此,它们在移动时,很可能会在页面加载期间获取新版本。

答案 2 :(得分:1)

我知道我在这个问题上有点迟到了,但是我建议您更改部署方式。

签出https://immutablewebapps.org/。基本原理是将构建时间资产与运行时变量隔离。这提供了很多好处,但最大的好处是:

  • 资产没有缓存问题,因为它们是在路由级别隔离的
  • 在生产中使用了经过开发审查的相同代码
  • 在出现问题的情况下为消费者提供即时回退和热缓存
  • 为通过路由隔离的先前版本维护创建的块,从而避免了活动部署与活动用户的问题

这也不应干扰下面@dottodot提供的** PreloadAllModules **建议。

答案 3 :(得分:0)

禁用块的散列

ng build --output-hashing none

有关详情,请参阅官方版本documentation

答案 4 :(得分:0)

您可以从服务器端发送一些事件来重新加载应用程序。此外,还可以选择在后台预先获取延迟模块,以便尽快预取它们,而不是等待模块的请求。

答案 5 :(得分:0)

使用预加载。您可以获得延迟加载的好处,而不会在这种情况下造成麻烦。所有块都将尽快提供给用户,而不会减慢初始加载时间。以下是https://vsavkin.com/angular-router-preloading-modules-ba3c75e424cb的摘录,以解释其工作原理(请参阅该图以了解图表):

  

首先,我们加载初始包,其中仅包含组件   我们必须引导我们的应用程序。如此之快   可以。

     

然后,我们使用这个小捆绑包引导应用程序。

     

此时应用程序正在运行,因此用户可以启动   与之互动。当她这样做时,我们在后台   预加载其他模块。

     

最后,当她单击转到可延迟加载的模块的链接时,   导航是即时的。

     

我们两全其美:初始加载时间短至   可以,随后的导航是即时的。

答案 6 :(得分:0)

我遇到了同样的问题,并且找到了一个非常简洁的解决方案,其他答案中没有提到。

您使用全局错误处理,如果块失败,则强制应用重新加载。

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

这是一个简单的解决方案,here (Angular Lazy Routes & loading chunk failed)是我从中获得的文章。

答案 7 :(得分:0)

您还可以使用服务人员通过“轮询/间隔”来检测更改,并通知用户进行应用更新。

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

例如,服务工作人员可以每1分钟检测一次,例如是否有新的“资产/您的应用”,并向上滑动以通知用户重新加载页面,或者如果需要的话,可以强制页面。

答案 8 :(得分:-4)

清除浏览器缓存。为我工作