この記事は Angular Advent Calendar 2020 10日目の記事です
はじめに
【Angular】これからはじめるE2Eテスト(2019)を書いていた1年前はAngular8までしかリリースされていなかったのに、もう11までリリースされ時が経つのは早いなぁ…と思うこの頃です。
この記事では、そのような進化の早いAngularで
- 「ビルド時間やバンドルサイズが改善されたとか聞くけど、どれ位改善されているの?ng updateで簡単にアップデートできるけど検証大変だしなぁ…」
- 「ビルド時間が早くなったらもっと効率上がるのに…」
- 「バンドルサイズが減れば初回ロードをもっと早くできるのに…」
みたいな事を考えている方に、Angularをアップデートするモチベーションの
後押しをできたらと思い、実際に色々なメジャーバージョン毎に簡単に計測してみた結果を紹介していきたいと思います。
※ ご使用の端末のスペック、プロジェクト、負荷状況により思った通りの結果とは異なってくると思いますが
何かの参考になれば幸いです。
対象読者
- Angularを8〜11にかけてどれくらい「ビルド時間やバンドルサイズが改善されたか」ざっくり知りたい方
実行環境
- MacBook Pro (13-inch, 2017, Two Thunderbolt 3 ports)
- プロセッサ:2.3 GHz Intel Core i5
- メモリ:16 GB 2133 MHz LPDDR3
① かんたんなサンプルで試してみる
まずは、去年Angular8で作成したログイン画面があるような サンプルで各バージョン毎のビルド時間やバンドルサイズを計測してみました。
ソースコードのステップ数を計測する
まずは、そもそもどれくらいの規模感のコード量だったのか
cloc を利用して、ソースコードの規模を計測して肌感を掴んでみます。
-> % cloc src
19 text files.
19 unique files.
2 files ignored.
github.com/AlDanial/cloc v 1.88 T=0.03 s (638.2 files/s, 24386.1 lines/s)
-------------------------------------------------------------------------------
Language files blank comment code
-------------------------------------------------------------------------------
CSS 1 44 2 244
TypeScript 13 31 71 162
HTML 4 16 1 148
Sass 1 1 0 6
-------------------------------------------------------------------------------
SUM: 19 92 74 560
------------------------
各項目の定義
項目 説明
-----------------
files ファイル数
blank 空行数
comment コメント行数(ファイルの拡張子から言語を判断し、 言語別に定義されたフィルター に従って行数を算出する)
code 論理LOC(物理LOCから空行数とコメント行数を除いた行数)
Angular Material位しか追加のライブラリは使用していないので
これ位のcode数になるのかなぁといった感じです。
ng serveとng buildを計測してみる
上記プロジェクトに対して、異なる Angular+CLI のバージョンで
- ng serve
- ng build --prod
で各Angularのメジャーバージョンの最新毎に、どの程度ビルド時間やバンドルサイズに違いがあるか計測してみます。
※ 各バージョン毎のサンプルコードは以下のリポジトリに置いております。
ng serve
Angular+CLI | 1回目 | 2回目 | 3回目 | 平均 | total size | main.js | polyfills.js | polyfills-es5.js | runtime.js | styles.js or .css | vendor.js |
---|---|---|---|---|---|---|---|---|---|---|---|
8.2.14 + 8.3.29 | 12085 ms | 10669 ms | 10878 ms | 11211 ms | 8.71 MB | 49.5 kB | 288 kB | 624 kB | 6.15 kB | 189 kB | 7.58 MB |
9.1.12 + 9.1.12 | 12041 ms | 10743 ms | 10975 ms | 11253 ms | 8.17 MB | 49.8 kB | 166 kB | 604 kB | 6.15 kB | 165 kB | 7.2 MB |
10.2.3 + 10.2.0 | 12102 ms | 12164 ms | 12814 ms | 12360 ms | 5.15 MB | 48.2 kB | 143 kB | 527 kB | 6.15 kB | 180 kB | 4.27 MB |
11.0.3 + 11.0.3 | 12664 ms | 12960 ms | 12777 ms | 12800 ms | 5.08 MB | 48.18 kB | 142.88 kB | 526.47 kB | 6.15 kB | 75.00 kB | 4.30 MB |
ng build --prod
Angular+CLI | 1回目 | 2回目 | 3回目 | 平均 | total size | main | polyfills | polyfills-es5 | runtime | styles |
---|---|---|---|---|---|---|---|---|---|---|
8.2.14 + 8.3.29 | 22352 ms | 18951 ms | 18700 ms | 20001 ms | 0.707 MB | 477 kB | 49.2 kB | 132 kB | 1.45 kB | 64.7 kB |
9.1.12 + 9.1.12 | 29388 ms | 23297 ms | 22474 ms | 25053 ms | 0.680 MB | 458 kB | 44.2 kB | 127 kB | 1.45 kB | 65.2 kB |
10.2.3 + 10.2.0 | 22987 ms | 18982 ms | 18973 ms | 20314 ms | 0.693 MB | 466 kB | 44 kB | 127 kB | 1.45 kB | 71.2 kB |
11.0.3 + 11.0.3 | 18311 ms | 18012 ms | 19262 ms | 18528 ms | 0.691 MB | 463.61 kB | 43.93 kB | 126.60 kB | 1.45 kB | 71.70 kB |
ng serveでは、外部ライブラリをまとめるvendor.jsやstyle.jsが 9 → 10,11で半分近く削減されており全体のサイズで42%近く削減されている感じです。
nb buildは11だとビルド時間が少しだけ早くなっているような気がしますが、元々のコード数がそれほどでもないのもあり
1~2s位の差しかないものの、少しビルド時間が改善されてそうな雰囲気でした。
バンドルファイルのサイズを可視化してみる
少し視点を変えて
webpack-bundle-analyzer を利用してバンドルファイル内の容量を可視化して
何か気づけるポイントがないかざっくり確認してみます。
Angular9.1.12
Angular9からivyなる単語が出てきました。
modules数も若干減っているようです。
Angular10.2.3
ES5サポートされなくなった代わりにデフォルトのターゲットとしてes2015が登場してきました。
modules数が増えてます
Angular11.0.3
10とあまり変わらないような気がします。
これらをみてみて何かできるかというと…何ともといった印象です。
出力結果
以下実行した際の、ターミナルの出力結果になります。
**8.2.14**
### ng serve
-> % npx ng serve
10% building 4/4 modules 0 activeℹ 「wds」: Project is running at http://localhost:4200/webpack-dev-server/
ℹ 「wds」: webpack output is served from /
ℹ 「wds」: 404s will fallback to //index.html
chunk {main} main.js, main.js.map (main) 49.5 kB [initial] [rendered]
chunk {polyfills} polyfills.js, polyfills.js.map (polyfills) 288 kB [initial] [rendered]
chunk {polyfills-es5} polyfills-es5.js, polyfills-es5.js.map (polyfills-es5) 624 kB [initial] [rendered]
chunk {runtime} runtime.js, runtime.js.map (runtime) 6.15 kB [entry] [rendered]
chunk {styles} styles.js, styles.js.map (styles) 189 kB [initial] [rendered]
chunk {vendor} vendor.js, vendor.js.map (vendor) 7.58 MB [initial] [rendered]
Date: 2020-11-28T06:38:37.677Z - Hash: 6d05494f1054751c5c56 - Time: 12085ms
** Angular Live Development Server is listening on localhost:4200, open your browser on http://localhost:4200/ **
ℹ 「wdm」: Compiled successfully.
### ng build
npx ng build --prod
chunk {0} runtime.7d9d4678f9511567f211.js (runtime) 1.45 kB [entry] [rendered]
chunk {1} main.e1e6747dc78a7df735d9.js (main) 477 kB [initial] [rendered]
chunk {2} polyfills.9e5f02ddbbe9b6461c4d.js (polyfills) 49.2 kB [initial] [rendered]
chunk {3} polyfills-es5.42546bc6cf833c6c55c3.js (polyfills-es5) 132 kB [initial] [rendered]
chunk {4} styles.b18eab1ab047affe392a.css (styles) 64.7 kB [initial] [rendered]
Date: 2020-11-28T06:44:42.691Z - Hash: 2a3728b8ba90de3e9d12 - Time: 29388ms
**9.1.12**
### ng serve
npx ng serve
chunk {main} main.js, main.js.map (main) 49.8 kB [initial] [rendered]
chunk {polyfills} polyfills.js, polyfills.js.map (polyfills) 166 kB [initial] [rendered]
chunk {polyfills-es5} polyfills-es5.js, polyfills-es5.js.map (polyfills-es5) 604 kB [initial] [rendered]
chunk {runtime} runtime.js, runtime.js.map (runtime) 6.15 kB [entry] [rendered]
chunk {styles} styles.js, styles.js.map (styles) 165 kB [initial] [rendered]
chunk {vendor} vendor.js, vendor.js.map (vendor) 7.2 MB [initial] [rendered]
Date: 2020-11-28T06:20:01.712Z - Hash: c1a954302bfed96979c5 - Time: 12041ms
** Angular Live Development Server is listening on localhost:4200, open your browser on http://localhost:4200/ **
: Compiled successfully.
### ng build
npx ng build --prod
chunk {} runtime.c51bd5b1c616d9ffddc1.js (runtime) 1.45 kB [entry] [rendered]
chunk {1} main.9d11a5f782d1d971fb7e.js (main) 458 kB [initial] [rendered]
chunk {2} polyfills.71d87feb638b7fba08d7.js (polyfills) 44.2 kB [initial] [rendered]
chunk {3} polyfills-es5.843dac686aeed00f071b.js (polyfills-es5) 127 kB [initial] [rendered]
chunk {4} styles.2fb9cdfa6c31fb771bc9.css (styles) 65.2 kB [initial] [rendered]
Date: 2020-11-28T06:27:48.581Z - Hash: f18607da46a22acc25f0 - Time: 42834ms
**10.2.3**
### ng serve
npx ng serve
chunk {main} main.js, main.js.map (main) 48.2 kB [initial] [rendered]
chunk {polyfills} polyfills.js, polyfills.js.map (polyfills) 143 kB [initial] [rendered]
chunk {polyfills-es5} polyfills-es5.js, polyfills-es5.js.map (polyfills-es5) 527 kB [initial] [rendered]
chunk {runtime} runtime.js, runtime.js.map (runtime) 6.15 kB [entry] [rendered]
chunk {styles} styles.js, styles.js.map (styles) 180 kB [initial] [rendered]
chunk {vendor} vendor.js, vendor.js.map (vendor) 4.27 MB [initial] [rendered]
Date: 2020-11-28T07:15:48.442Z - Hash: 589bffe80031e3d51fb7 - Time: 15335ms
** Angular Live Development Server is listening on localhost:4200, open your browser on http://localhost:4200/ **
: Compiled successfully.
### ng build
npx ng build --prod
chunk {} runtime.acf0dec4155e77772545.js (runtime) 1.45 kB [entry] [rendered]
chunk {1} main.f90c189d8cd3e4c51845.js (main) 466 kB [initial] [rendered]
chunk {2} polyfills.c94831f2a1f364f1a4a5.js (polyfills) 44 kB [initial] [rendered]
chunk {3} polyfills-es5.7c743eeca033b364400e.js (polyfills-es5) 127 kB [initial] [rendered]
chunk {4} styles.13264c032b9d7a48a006.css (styles) 71.2 kB [initial] [rendered]
Date: 2020-11-28T07:27:31.492Z - Hash: c808902f305f618545d8 - Time: 18982ms
**11.0.3**
### ng serve
npx ng serve
✔ Browser application bundle generation complete.
Initial Chunk Files | Names | Size
vendor.js | vendor | 4.30 MB
polyfills-es5.js | polyfills-es5 | 526.47 kB
polyfills.js | polyfills | 142.88 kB
styles.css | styles | 75.00 kB
main.js | main | 48.18 kB
runtime.js | runtime | 6.15 kB
| Initial Total | 5.08 MB
Build at: 2020-11-28T07:39:53.536Z - Hash: 4acbc73b574bfd1959c6 - Time: 12664ms
** Angular Live Development Server is listening on localhost:4200, open your browser on http://localhost:4200/ **
✔ Compiled successfully.
### ng build
npx ng build --prod
✔ Browser application bundle generation complete.
✔ Copying assets complete.
✔ Index html generation complete.
Initial Chunk Files | Names | Size
main.fae9d5f691ae17348863.js | main | 463.61 kB
polyfills-es5.9c2ee4068feaf60cd9f8.js | polyfills-es5 | 126.60 kB
styles.1f0c68c5727076f41762.css | styles | 71.70 kB
polyfills.156882208aaba3a4b9c4.js | polyfills | 43.93 kB
runtime.359d5ee4682f20e936e9.js | runtime | 1.45 kB
| Initial Total | 707.29 kB
Build at: 2020-11-28T07:47:16.501Z - Hash: 18273bfa8aac8a5b2e9e - Time: 18311ms
色々見てみた感想
Angular11になってCLIの出力がよりみやすなっていていいなぁ…と思いつつ
肝心のビルド時間やmainのバンドルサイズがあまり改善されているような気が正直しません…
そこで
サンプルみたいな規模が小さいものでなく、実サービスで運用しているような、もう少し規模の大きいプロジェクトではどうなるか?
恐らくここが一番この記事で大事な所なので、こちらも各メジャーバージョン毎に計測してみました。
② もう少し大きめの規模のプロジェクトで計測してみる
サンプルプロジェクトではビルド速度などにあまり違いがありませんでしたが、
サンプルの 200倍 近いcode数のAngularプロジェクトに対して、大きく改善されるか確認していきます。
-> % cloc src
1537 text files.
Unique: 100 files Unique: 200 files Unique: 300 files Unique: 400 files Unique: 500 files Unique: 600 files Unique: 700 files Unique: 800 files Unique: 900 files Unique: 1000 files Unique: 1100 files Unique: 1200 files 1485 unique files.
77 files ignored.
github.com/AlDanial/cloc v 1.88 T=1.36 s (1088.8 files/s, 101447.2 lines/s)
-------------------------------------------------------------------------------
Language files blank comment code
-------------------------------------------------------------------------------
TypeScript 893 10415 502 92050
HTML 428 635 144 25972
Sass 131 615 37 3455
CSS 7 479 174 2765
JavaScript 3 0 24 329
JSON 7 3 0 210
SVG 11 0 8 181
Markdown 2 12 0 76
-------------------------------------------------------------------------------
SUM: 1482 12159 889 125038
ng serveとng buildを計測してみる
ng serve
Angular+CLI | 1回目 | 2回目 | 3回目 | 平均 | total size | main.js | polyfills.js | polyfills-es5.js | runtime.js | styles.js or css | vendor.js | scripts.js |
---|---|---|---|---|---|---|---|---|---|---|---|---|
8.2.14 + 8.3.29 | 47623 ms | 49221 ms | 48131 ms | 48325 ms | 19.70MB | 9.61MB | 123 kB | 444 kB | 6.15 kB | 960 kB | 7.26 MB | 643 kB |
10.2.3+10.2.0 | 71057 ms | 78990 ms | 71859 ms | 73969 ms | 24.08MB | 13.9MB | - | 419 kB | 6.15 kB | 774 kB | 8.38 MB | 646 kB |
11.0.3 + 11.0.3 | 95375 ms | 91234 ms | 87563 ms | 91391 ms | 24.30MB | 13.56 MB | - | 418.43 kB | 6.15 kB | 933.00 kB | 8.78 MB | 646.23 kB |
ng build --prod
Angular + CLI | 1回目 | 2回目 | 3回目 | 平均 | total size | main | polyfills-es5 | runtime | styles | scripts.js |
---|---|---|---|---|---|---|---|---|---|---|
8.2.14 + 8.3.29 | 142326 ms | 143689 ms | 141689 ms | 142568 ms | 9.07 MB | 8.31 MB | 79.6 kB | 1.45 kB | 197 kB | 501 kB |
10.2.3 + 10.2.0 | 87699 ms | 83409 ms | 80108 ms | 83739 ms | 7.73 MB | 6.96 MB | 83 kB | 1.45 kB | 199 kB | 507 kB |
11.0.3 + 11.0.3 | 83872 ms | 81685 ms | 96651 ms | 87403 ms | 7.66 MB | 6.89 MB | 82.75 kB | 1.45 kB | 198.99 kB | 506.62 kB |
ビルドに2分20秒以上(142568ms)かかっていたのが、Angular10, 11から半分の1分23秒位(83739ms)に…
バンドルサイズのtotalも1.41MBも減りました。
もっと改善する余地はないか?
webpack-bundle-analyzerでよくやり玉にあがってくる
moment.js周りの使用していないlocalizeが多々含まれているのでまだまだ起動時間などは改善できる余地はありそうです…
参考:【Angular6】angular-cli を拡張してMoment.js の locale を落とし bundle サイズを削減する
おわりに
個人的に、Angularのアップデートは本当に手厚くサポートされていると感じており
Angular Update Guideといったドキュメントや多くのissueなどの情報があるおかげて、コンパイルエラーにならない所までもっていくのは常に情報をキャッチアップしていればそこまで大変ではないのかなという肌感です。
※ 使用しているUIライブラリなどによっては一部正しく動かなかったりして泣きながら修正はちょこちょこしていましたが…
こういったフレームワークや言語のアップデートは
自分達のコード設計やテスト戦略とリリース戦略の見直しの一つのふり返りや、改善できる1つのポイントだと思いますし
メンテナンスを後回しにすると、新しい技術や言語の恩恵にあずかれなかったり
セキュリティ的な問題が発生した場合にサポートされなかったり…後々つけを払うことにもなりかねないと思います。
ぜひ、前向きにアップデートすることを検討できたらなと思います!
11日目は @studioTeaTwo さんです。よろしくお願いします!