Angular 中的路由级代码拆分

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

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

您可以在 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 提前路由。

8.1.0 版 Angular CLI 可以通过以下命令为您完成所有操作:

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

这将生成: - 一个名为 NyanModule 的新路由模块 - 一个名为 nyanAppModule 中的路由,用于动态加载 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.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. 在用户导航到延迟路线时添加加载指示器,以显示有正在进行的操作。