Angularの3種類のLoad方法について

最近Angularの勉強をやっているのでメモ半分でアウトプットしようと思います!今回はAngularのWebページのロード方法についての解説です.

通常のLoad

まずは通常のロードを使用した例をお見せしようと思います.このパターンは全てのページのモジュールを初回アクセス時に取得します.コードは以下にあげています. https://github.com/Yoshiaki-Harada/angular-lazy-load

今回はHOMEというページとSAMPLEというページを用意しました.SAMPLEというページにはchild1とchild2コンポーネントが埋め込まれています.HOMEからSAMPLEに飛べるように作成しています.

HOME
<h3> HOME </h3>
<br>
<ul>
    <li><a [routerLink]="[ '/sample' ]">Sample</a></li>
</ul>
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit {

  constructor() { }

  ngOnInit(): void {
  }

}

SAMPLE

<h3>SAMPLE PAGE</h3>
<p>
    This is Sample Page
</p>
<app-child1></app-child1>
<app-child2></app-child2>

CHILD

<p>child1 works!</p>
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-child1',
  templateUrl: './child1.component.html',
  styleUrls: ['./child1.component.scss']
})
export class Child1Component implements OnInit {

  constructor() { }

  ngOnInit(): void {
  }

}

child2はchild1とほぼ同じなので割愛します.

Routing

これらのHOMEページとSAMPLEページをRoutingに登録します.

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

const routes: Routes = [
  { path: '', component: HomeComponent },
  { path: 'sample', component: SampleComponent },
];

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

プロジェクトを作成するときにrouteモジュールをimportするにyesと答えた場合app-routing.moduleというファイルは自動で生成されます.このroutesに自分が作成したコンポーネントを登録します. またこのrouteに登録したページを表示するにはapp.component.htmlで以下のように<router-outlet></router-outlet>を登録する必要があります.

<router-outlet></router-outlet>
アクセス結果

アプリケーションをたて,接続してみるとmain.jsが22.5kBとなっています. f:id:harada-777:20201202205503p:plain

次にSampleページをクリックします. f:id:harada-777:20201202205457p:plain

特に追加でmoduleがロードされている様子はみられません.このように通常では全て最初にロードされます.

Lazy Load

次にそのページにアクセスされたタイミングはじめてロードするようにSampleページを作った場合を解説します.

Lazy Loadへの対応

lazy loadを実現するにはまずsample.module.tsを作成します.こちら先ほどのsample.component.tsと同階層に作成します.Child1Componet,Child2Componetもここで読み込むようにします.

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

import { SampleRoutingModule } from './sample-routing.module';
import { SampleComponent } from './sample.component';
import { Child1Component } from './child1/child1.component';
import { Child2Component } from './child2/child2.component';


@NgModule({
  declarations: [SampleComponent, Child1Component, Child2Component],
  imports: [
    CommonModule,
    SampleRoutingModule
  ]
})
export class SampleModule { }

次にsample-routing.moduleを作成します.

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

import { SampleComponent } from './sample.component';

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

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

次にapp-routing.moduleを以下のように変更します.

const routes: Routes = [
  { path: '', component: HomeComponent },
  { path: 'sample', loadChildren: () => import('./sample/sample.module').then(m => m.SampleModule) }
];

このloadChiledrenの部分がポイントで,pathのsampleにアクセスされてはじめてロードするということを表しています. このコードは以下のコマンドを打つことで自動で生成することもできます.

ng g module sample --module app --route sample
アクセス結果

実際にアクセスしてみます. f:id:harada-777:20201202205451p:plain

main.jsのサイズが22.5kBより大分小さくなっていることが確認できます.このときSampleモジュールはまだロードされていないからです. 次にSampleページに飛んでみます. f:id:harada-777:20201202205446p:plain

sample-sample-module.jsがこのタイミングでロードされたことがわかります.このように遅延ロードを活用すると,最初のページに必要なモジュールを減らし,初めのページを表示する速度を早めることができます.

Pre Load

Pre loadとは初回のページはLazy Load通りに表示されるのですが,後でロードしてくるモジュールを,その後すぐにloadするというロード方法です.Lazy Loadでは訪れてはじめてloadされますが,Pre Loadは裏で先に準備しておくという感じです.

Pre Loadへの対応

app-routing.module.tsRouterModule.forRootにオプションとしてpreloadingStrategy:PreloadAllModulesを渡すだけPre Loadは実現できます.preloadingStrategyには他にもQuicklinkStrategyなどがあるそうです.

const routes: Routes = [
  { path: '', component: HomeComponent },
  { path: 'sample', loadChildren: () => import('./sample/sample.module').then(m => m.SampleModule) }
];

@NgModule({
  imports: [RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules })],
  exports: [RouterModule]
})
export class AppRoutingModule { }
アクセス結果

f:id:harada-777:20201202205508p:plain

このようにmain.jsがロードされた後でsample-sample-module.jsがロードされていることがわかります. 裏で初回ページは軽くしたいが,裏でロードしておいてして欲しい!って時にはこのPre Loadを使うのがいいと思います.

まとめ

Angularの3つのロード方法について解説しました.angular cliを使えば簡単にLazy Loadを使ったmoduleを作成できるので複数のページがあるアプリケーションを作りたい方はぜひ使うべきだなと感じました!!