Angular 中的路由级代码拆分

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

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

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

为什么代码拆分很重要

网络应用变得越来越复杂,使得提供给用户的 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 即刻路由。

Angular CLI 8.1.0 版可以使用以下命令执行所有操作:

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. 按 `Ctrl+Shift+J`(在 Mac 上,按 `Command+Option+J`)打开开发者工具。
  2. 点击网络标签页。

  3. 点击示例应用中的 NYAN

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

使用路由级代码拆分延迟加载 JavaScript 软件包

在 GitHub 上查找此示例。

显示旋转图标

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

为此,请先在 app.component.html 中的 router-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. 在用户导航到延迟路线时添加加载指示器,以显示有正在进行的操作。