Angular 中的路由级代码拆分

使用路由级代码拆分,提升应用的性能!

这篇博文将介绍如何在 Angular 应用中设置路线级代码拆分,这可以缩减 JavaScript 软件包的大小并显著缩短可交互时间

您可以在 GitHub 上找到本文中的代码示例。Eager 分支中提供了 Eager 路由示例。路由级代码拆分示例位于延迟分支中。

为什么代码拆分很重要

随着 Web 应用的复杂性不断增加,提供给用户的 JavaScript 数量大幅增加。大型 JavaScript 文件可能会明显延迟互动,因此这项资源成本可能很高,尤其是在移动设备上。

若要在不牺牲应用功能的情况下缩减 JavaScript 软件包,最有效的方法是引入激进的代码拆分。

代码拆分可让您将应用的 JavaScript 拆分为多个与不同路由或功能相关联的区块。这种方法只会在应用初始加载期间向用户发送他们需要的 JavaScript,从而缩短加载时间。

代码拆分技术

代码拆分可在两个级别进行:组件级别和路由级别。

  • 在组件级代码拆分中,您需要将组件移动到它们各自的 JavaScript 块中,并在需要时延迟加载它们。
  • 在路由级代码拆分中,您需要将每个路由的功能封装为一个单独的块。当用户浏览您的应用时,他们会提取与单个路由关联的区块,并在他们需要时获取关联的功能。

这篇博文重点介绍了在 Angular 中设置路线级拆分。

示例应用

在深入了解如何在 Angular 中使用路线级代码拆分之前,我们先来看一个示例应用:

查看应用模块的实现。在 AppModule 中定义了两个路由:与 HomeComponent 关联的默认路由和与 NyanComponent 关联的 nyan 路由:

@NgModule({
  ...
  imports: [
    BrowserModule,
    RouterModule.forRoot([
      {
        path: '',
        component: HomeComponent,
        pathMatch: 'full'
      },
      {
        path: 'nyan',
        component: NyanComponent
      }
    ])
  ],
  ...
})
export class AppModule {}

路由级代码拆分

如需设置代码拆分,需要重构 nyan Eager 路由。

8.1.0 版本的 Angular CLI 可以使用以下命令代您完成一切工作:

ng g module nyan --module app --route nyan

这将生成: - 一个名为 NyanModule 的新路线模块 - AppModule 中一个名为 nyan 的路线,该路线将动态加载 NyanModule - NyanModule 中的默认路线 - 一个会在用户到达默认路线时呈现的名为 NyanComponent 的组件

下面我们手动执行这些步骤,以便更好地了解如何使用 Angular 实现代码拆分!

当用户导航到 nyan 路线时,路由器会在路由器插座中渲染 NyanComponent

如需在 Angular 中使用路线级代码拆分,请设置路线声明的 loadChildren 属性,并将其与动态导入相结合:

{
  path: 'nyan',
  loadChildren: () => import('./nyan/nyan.module').then(m => m.NyanModule)
}

与紧急路由有两大主要区别:

  1. 您设置了 loadChildren,而不是 component。使用路由级代码拆分时,您需要指向动态加载的模块,而不是组件。
  2. loadChildren 中,当 promise 得到解析后,系统会返回 NyanModule,而不是指向 NyanComponent

上面的代码段指定,当用户导航到 nyan 时,Angular 应从 nyan 目录动态加载 nyan.module,并呈现与模块中声明的默认路线相关联的组件。

您可以使用此声明将默认路线与组件相关联:

import { NgModule } from '@angular/core';
import { NyanComponent } from './nyan.component';
import { RouterModule } from '@angular/router';

@NgModule({
  declarations: [NyanComponent],
  imports: [
    RouterModule.forChild([{
      path: '',
      pathMatch: 'full',
      component: NyanComponent
    }])
  ]
})
export class NyanModule {}

当用户导航到 https://example.com/nyan 时,此代码会呈现 NyanComponent

如需检查 Angular 路由器是否在您的本地环境中延迟下载 nyan.module,请执行以下操作:

  1. 按 `Control+Shift+J`(在 Mac 上,则按 `Command+Option+J`)打开开发者工具。
  2. 点击网络标签页。

  3. 点击示例应用中的 NYAN

  4. 请注意,nyan-nyan-module.js 文件会显示在“Network”标签页中。

通过路由级代码拆分延迟加载 JavaScript 软件包

在 GitHub 上查找此示例。

显示旋转图标

目前,当用户点击 NYAN 按钮时,应用并未指示它正在后台加载 JavaScript。要在加载脚本时向用户提供反馈,您可能需要添加一个旋转图标。

为此,请先在 app.component.htmlrouter-outlet 元素内为指示器添加标记:

<router-outlet>
  <span class="loader" *ngIf="loading"></span>
</router-outlet>

然后,添加一个 AppComponent 类来处理路由事件。此类会在收到 RouteConfigLoadStart 事件时将 loading 标志设置为 true,并在检测到 RouteConfigLoadEnd 事件时将标志设置为 false

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  loading: boolean;
  constructor(router: Router) {
    this.loading = false;
    router.events.subscribe(
      (event: RouterEvent): void => {
        if (event instanceof NavigationStart) {
          this.loading = true;
        } else if (event instanceof NavigationEnd) {
          this.loading = false;
        }
      }
    );
  }
}

在下面的示例中,我们人为引入了 500 毫秒的延迟,以便您看到旋转图标的实际效果。

总结

您可以通过应用路线级代码拆分来缩减 Angular 应用的软件包大小:

  1. 使用 Angular CLI 延迟加载模块生成器自动生成动态加载路由的基架。
  2. 在用户导航到延迟路由时添加加载指示器,以显示正在进行的操作。