【Angular】ページの表示速度アップ!Lazyloadを使って初期ページの読み込みデータを小さくする

どうも!大阪オフィスの西村祐二です。

SPAでサイトを作っていると機能追加などでどんどんコンポーネントが肥大化してしまい表示までに時間がかかることがあると思います。

AngularではLazyloadモジュールという遅延読み込みを行うことができる機能が提供されており、必要なファイルだけ読み込むように設定することができます。

具体例をあげると

サイトにアクセスした際にログイン画面が表示されるサイトがあるとします。 LazyLoadモジュールを使いログイン画面にアクセスしたときはログインに関するデータだけ読み込み、他のデータはログイン後に読み込むといったことが実現できます。

これにより、最初に読み込むコンテンツの量を減らして、初期ページの読み込みの高速化が期待できます。

やってみる

環境

Angular CLI: 7.0.2
Node: 8.11.3
OS: darwin x64
Angular: 7.0.0
... animations, common, compiler, compiler-cli, core, forms
... http, language-service, platform-browser
... platform-browser-dynamic, router

Package                           Version
-----------------------------------------------------------
@angular-devkit/architect         0.10.2
@angular-devkit/build-angular     0.10.2
@angular-devkit/build-optimizer   0.10.2
@angular-devkit/build-webpack     0.10.2
@angular-devkit/core              7.0.2
@angular-devkit/schematics        7.0.2
@angular/cli                      7.0.2
@ngtools/webpack                  7.0.2
@schematics/angular               7.0.2
@schematics/update                0.10.2
rxjs                              6.3.3
typescript                        3.1.3
webpack                           4.19.1

プロジェクト作成

$ ng new lazyload --routing
$ cd lazyload

コンポーネント作成

$ ng g c home

モジュール作成

遅延読み込みをさせるためにモジュールを作成します。名前は好きな名前で大丈夫です。

--routingを忘れずに。

これをつけることでforChildとなる親ファイルと紐づくルーティングファイルを自動的に作成してくれます。

$ ng g module Lazy --routing

遅延読み込みさせたいコンポーネントを作成

$ ng g c lazy/lazy-page --module Lazy

作成が完了すると追加したlazy.module.tsにlazy-pageコンポーネントが追記されているかと思います。

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';

import { LazyRoutingModule } from './lazy-routing.module';
import { LazyPageComponent } from '../lazy/lazy-page/lazy-page.component';

@NgModule({
  imports: [
    CommonModule,
    LazyRoutingModule
  ],
  declarations: [LazyPageComponent]
})
export class LazyModule { }

ルーティング

いつもの通りにルーティング設定します。

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { LazyPageComponent } from './lazy-page/lazy-page.component';

const routes: Routes = [
  {
    path: '',
    component: LazyPageComponent
  }
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class LazyRoutingModule {}

loadChildrenとしてモジュールを指定することによって遅延読み込みをしてくれるようになります。

似たような構文でchildrenがありますが、こちらは遅延読み込みにならないので注意ください。

import { HomeComponent } from './home/home.component';
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

const routes: Routes = [
  {
    path: '',
    component: HomeComponent
  },
  {
    path: 'lazy',
    loadChildren: './lazy/lazy.module#LazyModule'
  },
  {
    path: '**',
    redirectTo: ''
  }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule {}

画面

挙動がわかりやすいようにボタン配置し、「LazyPage」ボタンをクリックされたら、遅延読み込みに指定したファイルが読み込まれるようにしています。

つまり、Homeコンポーネントしかはじめは読み込まれていないということになります。

<h1>
  {{title}}
</h1>

<button routerLink="/lazy">LazyPage</button>
<button routerLink="">Home</button>

<router-outlet></router-outlet>

下記のような画面になっているかと思います。

イメージ図

遅延読み込みのイメージとしては下記の図のようにボタンがクリックされたら、LazyPageコンポーネントが読み込まれるイメージをしていただければよいかと思います。

それまでは読み込まれないので、最初に読み込むコンテンツの量を減らすことができたということになります。

動作確認

ChromeのDevツールを使って確認します。

  • ボタンクリック前

  • ボタンクリック後

プロダクションビルドしたときの出力ファイル

LazyLoadモジュールを使うときのちょっとした注意点としては、遅延読み込みするためにファイル分割する必要があり、ビルドした後に出力されるファイル数が遅延読み込みする分増えるのでご注意ください。

  • 遅延読み込みなし

  • 遅延読み込みあり

さいごに

いかがだったでしょうか。

AngularのLazyLoadを使い、最初に読み込むコンテンツの量を減らす方法を紹介しました。

LazyLoadを使うことによって簡単に遅延読み込みをすることができ便利なのでどんどん使っていきたいと思います。

誰かの参考になれば幸いです。