Angular 中的路由级代码拆分

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

本文介绍了如何在 Angular 应用中设置路由级代码拆分,这可以减小 JavaScript 软件包大小并显著缩短Time to Interactive。

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

为什么代码拆分很重要

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 预先加载路由。

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

与 Eager 路由相比,主要有两点不同:

  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 文件会显示在“网络”标签页中。

通过路由级代码拆分延迟加载 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. 当用户导航到延迟加载路由时,添加加载指示器以显示正在执行的操作。