🧩

Ionic/Angularプロジェクトのモジュール単位を意識して開発しよう。

2021/12/01に公開

本記事は Ionic Framework / Capacitor / Stencil Advent Calendar 2021 Advent Calendar 2021 の初日の記事です。


Ionic/Angularプロジェクトのパフォーマンス最適化において、モジュール分割の最適化は避けて通ることができません。極端な例ですが、モジュール分割を1つもしないプロジェクトと、全ページ/コンポーネントを分割した場合を考えていきましょう。

モジュール分割の意味を理解する

Angularは、ページ、コンポーネント、サービス、ディレクティブなどはすべてngModuleに登録します。つまりAngularプロジェクトは1つ以上のngModuleで構成されており、その下位にページやコンポーネントが存在しています。

serviceはngModuleに登録しなくても動作しますが、これは providedIn: 'root' を指定した場合であり、この指定があるとルートインジェクターとして振る舞うことによるものです。

モジュールは共通利用するコンポーネントやディレクティブを登録する目的としてつくられたもの(よく sharedModule という言い方をします)以外はルーティングをもっており、当該URLへのアクセスをキックにして遅延読み込みされます。

  {
    path: 'tabs',
    loadChildren: () => import('./tabs/tabs.module').then((m) => m.TabsPageModule),
  },

と書かれてるのがまさにそれで、 tabs パスに遷移すると、 TabsPageModule の読み込みが行われます。

モジュール分割を1つもしないプロジェクト

では、モジュール分割をひとつもしないプロジェクトだとどういうように動作するのでしょうか。結果だけをいってしまうと、「最初に読み込むバンドルサイズが大きすぎて、初期表示に時間がかかる」ことになります。

もう超絶昔につくって、メンテも何もしていないIonic/Angularプロジェクトなのですが、

https://apps.rdlabo.jp/

をみてみてください。笑けるほど遅いです。当時はモジュール分割自体がAngularに実装されてなかったため、すべて1モジュールで実装されています(遅い要因はこれだけではないですが)

"@angular/core": "2.0.0-rc.4",
"ionic-angular": "2.0.0-beta.11",

まぁ、化石ですね。Single Page ApplicationはJSベースで描画を行うことから登場直後から最初に読み込まないといけないバンドルサイズの大きさと、初期表示の遅さが問題視されていました。ですので、現在ではモジュール分割が推奨されています。

すべてモジュール分割したプロジェクト

逆にすべてを細かくモジュール分割をすればいいのでしょうか。モジュール分割を1つもしないプロジェクトよりはベターといえますが、反面、ユーザの操作感を落とすことになります。

先程「モジュールの遅延読み込みは当該URLへのアクセスをキックに行われる」と紹介しました。言い換えれば、ユーザが当該URLに遷移してモジュールの読み込みがはじまり、それが完了してページが表示されます。具体的に Preloading modules in Ionic v4 からモジュール読み込みによる遅延を確認していきましょう。

まず、モジュール読み込みによる遅延が起きなかった場合です。

ページを選択するとすぐに遷移がはじまります。続いて、モジュール読み込みによる遅延が起きた場合です。

タップすると該当するモジュールの読み込みがはじまり、完了した時点で遷移がはじまっている(遅延している)様子がわかります。

モジュールの読み込みタイミングと規模を意識した開発を行おう

Ionic CLIで ionic g pg でつくるとすべてモジュール分割が行われます。このことからモジュール分割をすべてした状態のプロジェクトが比較的多いですが、ユーザ体験を損なってしまう可能性をもっています。

そのため重要なのは、モジュールの読み込みタイミングと規模を意識するようにすることです。

たとえば、Tabsをつかったプロジェクトだと、各Tabで表示する機能はそれぞれ1モジュールにまとめるであったり、その中でもめったに使われない機能(特にModalなど)は別Moduleにまとめてしまうと、初期で読み込むページとコンポーネント量はこれぐらいで、これをタップした時に次のModuleを読み込むのは適切だよねのようなストーリーを頭で描く必要があります。

たとえば、以下は私が開発を行っている tipsys のフォルダ構成ですが、これらのフォルダ毎に1つのモジュールを持っています。

なので、たとえばこの timeline フォルダだと以下のように、各コンポーネント、ページ、サービスが含まれています。

自分自身が開発している規模のプロジェクトだとどのモジュール規模がいいのかなど一度考えるようにしてみてください。

おわりに

モジュール分割については Ionicで作る モバイルアプリ制作入門[Angular版] のP158「モジュールをまとめよう」についても書いてありますので、やり方がわからないという方はぜひご参考ください。

それではまた。

Discussion