Angular 中的路徑層級程式碼分割

使用路徑層級的程式碼分割功能提升應用程式效能!

米科.吉切夫
Minko Gechev

本文說明如何在 Angular 應用程式中設定路徑層級的程式碼分割,藉此縮減 JavaScript 組合大小,並大幅改善互動時間

您可以在 GitHub 中找到本文的程式碼範例。如需緊急轉送範例,請參閱Eager 分支版本。路徑層級的程式碼分割範例位於「Lazy 分支版本」中。

程式碼分割功能的重要性

網頁應用程式日益複雜,使得提供給使用者的 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 中,承諾一旦解析,就會��回 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. 在使用者前往延遲路徑時新增載入指標,顯示目前有一項動作。