LoginSignup
13
2

More than 5 years have passed since last update.

AppShellモデルを適用してmain.bundleのサイズ削減する

Last updated at Posted at 2018-03-11

試したこと

  • AppShellモデルでモジュール構成を組み直す。1
  • そのために共有リソースをCoreModuleとSharedModuleに分割する。2
  • main.bundleのファイルサイズ削減を計測する。

環境

  • Angular:5.2.6
  • Angular-CLI:1.7.1

モジュール構成の戦略

AppModuleをAppShellモデルにする

スクリーンショット 2018-03-12 0.07.54.png

AppShellモデルのために、AppModuleは以下の役目だけを持たせます。

  • application shell
  • 各content(LazyLoadingModule)へのルーティング
  • DIコンテナの最上位ルート

これにより初回ロードに必要なmain.bundleは、AppShellだけになります。
アプリ全体だと次のようになります。

スクリーンショット 2018-03-13 15.25.25.png

各contentはLazyLoadingModuleへ回して、できるだけ共有リソースもAppModuleから外すことで、ユーザー作成ソースだけでなくベンダー系ソースも後送りにします。結果を見ると、ベンダー系ソースではAngularMaterialの効果が絶大です。

以上の変更によりmain.bundleがサイズ削減されて起動時間が短縮します。

元の構成

スクリーンショット 2018-03-11 22.22.22.png

  • 共有リソースをSharedModuleに全て突っ込んでいた
  • SharedModuleをAppModule含めたあらゆるモジュールでインポートする
  • 最上位のAppModuleでforRoot()によるシングルトンサービスを生成する
  • Rxはrxjs/add/からインポート

新しい構成

スクリーンショット 2018-03-11 22.19.46.png

  • SharedModuleとCoreModuleに分ける
  • AppModuleにCoreModuleをインポートする
  • 各LazyLoadingModuleにSharedModuleをインポートする
  • Rxをpipe化する

CoreModuleとSharedModuleの分け方

CoreModule

  • ナビゲーション系component
  • ナビゲーション系componentで使うdirective/pipe、materialモジュール
  • アプリ全体で使用するAngularパッケージ
    • BrowserAnimationsModule
    • HttpClientModule
    • ServiceWorkerModule
  • アプリ全体で使用するservice
  • app-routingで使用するguard

SharedModule

  • フィーチャーモジュールで使用するAngularパッケージ
    • CommonModule
    • FormsModule/ReactiveFormsModule
  • フィーチャーモジュールで使用する共有リソース
    • directive
    • pipe
    • guard
    • materialモジュール

共有serviceは全てCoreModuleに入れています。特定のフィーチャーモジュールだけで使うserviceなら特定のフィーチャーモジュールでprovideします(SharedModuleには入れません)。複数モジュールに跨るservideをSharedModuleに入れてしまうと、フィーチャーモジュール毎にコピーを生成します。そうなるとアプリ全体で見た時にシングルトンのサービスにならないため、データの共有できないことに注意です。

バンドルファイルのサイズ変化

サマリー

  • 後送りにした共有リソース分がmain.bundleからcommon.chunkに移動する。
  • --prodビルドのmain.bundleは、--aotビルドでのmain.bundleとvendor.bundleで構成されるが、--aotビルドでは以下の変化となる。
    • SharedModuleに回したユーザー作成リソースがmain.bundleからcommon.chunkに移動する。
    • Angularパッケージ系(FormsModuleやAngularMaterial)のソースがvendor.bundleからcommon.chunkに移動する。
    • RxJSはvendor.bundleのままで移動しない。これはvendor.bundle内のAngularパッケージが使用しているからだと思われる。
  • 微量だが、合計サイズも減った。要因は不明である。

集計方法

  1. 採取用のサンプルソースを作成した。
    • 元の状態はコミットrefactor: divide feature module from app module3である
    • 新しい状態はコミットrefactor: reconstruct module and reorganize rxjs4である
    • フィーチャーモジュールが一つのためcommon.chunkは作成されない。demo.chunkがsharedModuleを内包している。
  2. 上記2つのコミットに対して、--aotビルドと--prodビルドでそれぞれビルド結果を採取した。

--aotビルドでの変化

元の構成でのビルド結果

Time: 12854ms
chunk {demo.module} demo.module.chunk.js, demo.module.chunk.js.map () 51.4 kB  [rendered]
chunk {inline} inline.bundle.js, inline.bundle.js.map (inline) 5.83 kB [entry] [rendered]
chunk {main} main.bundle.js, main.bundle.js.map (main) 61.4 kB [initial] [rendered]
chunk {polyfills} polyfills.bundle.js, polyfills.bundle.js.map (polyfills) 325 kB [initial] [rendered]
chunk {styles} styles.bundle.js, styles.bundle.js.map (styles) 63.7 kB [initial] [rendered]
chunk {vendor} vendor.bundle.js, vendor.bundle.js.map (vendor) 3.88 MB [initial] [rendered]

新しい構成でのビルド結果

Time: 12936ms
chunk {demo.module} demo.module.chunk.js, demo.module.chunk.js.map () 2.04 MB  [rendered]
chunk {inline} inline.bundle.js, inline.bundle.js.map (inline) 5.83 kB [entry] [rendered]
chunk {main} main.bundle.js, main.bundle.js.map (main) 30.6 kB [initial] [rendered]
chunk {polyfills} polyfills.bundle.js, polyfills.bundle.js.map (polyfills) 325 kB [initial] [rendered]
chunk {styles} styles.bundle.js, styles.bundle.js.map (styles) 63.7 kB [initial] [rendered]
chunk {vendor} vendor.bundle.js, vendor.bundle.js.map (vendor) 1.88 MB [initial] [rendered]
ファイル 元の構成 新しい構成
main.bundle.js 61.4kB 30.6kB
vendor.bundle.js 3.88MB 1.88MB
demo.module.chunk.js 51.4kB 2.04MB
合計 3992.8kB 3950.6kB

特にvendor.bundleが2MBと大きく移動していることがわかる。今回のサンプルソースでは、ほぼAngularMaterialになる。

--prodビルドでの変化

元の構成でのビルド結果

Time: 28226ms
chunk {0} 0.aa68a6ffd1d68364462f.chunk.js () 8.04 kB  [rendered]
chunk {1} main.212ed5e5d1c0616288fd.bundle.js (main) 563 kB [initial] [rendered]
chunk {2} polyfills.57c88da6a6d2a800f78f.bundle.js (polyfills) 126 kB [initial] [rendered]
chunk {3} styles.60f2c673d6a13f4d5d86.bundle.css (styles) 46.8 kB [initial] [rendered]
chunk {4} inline.735dc2ac6d85cc81d4a0.bundle.js (inline) 1.4 kB [entry] [rendered]

新しい構成でのビルド結果

Time: 11336ms
chunk {0} 0.aaac215c03d911a8600c.chunk.js () 213 kB  [rendered]
chunk {1} polyfills.6a4c24b5ca42039de4fd.bundle.js (polyfills) 126 kB [initial] [rendered]
chunk {2} main.4a3d80967dfb1e57f705.bundle.js (main) 326 kB [initial] [rendered]
chunk {3} styles.60f2c673d6a13f4d5d86.bundle.css (styles) 46.8 kB [initial] [rendered]
chunk {4} inline.30a8d86ae20b87488c1f.bundle.js (inline) 1.4 kB [entry] [rendered]
ファイル 元の構成 新しい構成
main.bundle.js 563kB 326kB
0.chunk.js 8.04kB 213kB
合計 571.04kB 539kB

初回ロードで読み込まれるmain.bundleが約2/3に減った。

13
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
2