Angular 8→9→10→11でビルド時間がどれくらい早くなっているかみてみよう！

この記事は [Angular Advent Calendar 2020](https://qiita.com/advent-calendar/2020/angular) 10日目の記事です
# はじめに
[【Angular】これからはじめるE2Eテスト（2019）](https://qiita.com/nishiemon/items/d774c17476c9f7d8ad6a)を書いていた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で作成したログイン画面があるような **[サンプル](https://github.com/hiroyuki-nishi/angular-e2e/tree/dev/angular8/src)**で各バージョン毎のビルド時間やバンドルサイズを計測してみました。

<img width="500" alt="login.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54858/71898b83-5ad4-d305-9571-8ca10f1e995f.png">



### ソースコードのステップ数を計測する

まずは、そもそもどれくらいの規模感のコード量だったのか
 **[cloc](https://github.com/AlDanial/cloc)** を利用して、ソースコードの規模を計測して肌感を掴んでみます。

```.sh
-> % 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のメジャーバージョンの最新毎に、どの程度ビルド時間やバンドルサイズに違いがあるか計測してみます。



※ 各バージョン毎のサンプルコードは以下のリポジトリに置いております。

* [Angular8](https://github.com/hiroyuki-nishi/angular-e2e/tree/dev/angular8)
* [Angular9](https://github.com/hiroyuki-nishi/angular-e2e/tree/dev/angular9)
* [Angular10](https://github.com/hiroyuki-nishi/angular-e2e/tree/dev/angular10)
* [Angular11](https://github.com/hiroyuki-nishi/angular-e2e/tree/dev/angular11)

#### <font color="MediumBlue">ng serve</font>


|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|<font color="DeepPink">4.27 MB</font>|
|11.0.3 + 11.0.3|12664 ms|12960 ms|12777 ms|12800 ms|<font color="DeepPink">5.08 MB</font>|48.18 kB|142.88 kB|526.47 kB|6.15 kB|<font color="DeepPink">75.00 kB</font>|<font color="DeepPink">4.30 MB</font>|


#### <font color="Teal">ng build --prod</font>

|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|<font color="DeepPink">18528 ms</font>|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位の差しかないものの、少しビルド時間が改善されてそうな雰囲気でした。

**各バージョン毎のng buildの平均速度**
![sample_ng_build.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54858/a7a78acd-f51a-8f18-5c79-d90ea4ab6888.png)


### バンドルファイルのサイズを可視化してみる
少し視点を変えて
**[webpack-bundle-analyzer](https://www.npmjs.com/package/webpack-bundle-analyzer)** を利用してバンドルファイル内の容量を可視化して
何か気づけるポイントがないかざっくり確認してみます。

**Angular8.2.14**
<img width="500" alt="angular8" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54858/aa9a768e-c9a1-08e0-48ba-100711cb687a.png">

**Angular9.1.12**
Angular9からivyなる単語が出てきました。
modules数も若干減っているようです。
<img width="500" alt="angular9" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54858/2c393b8f-fecf-8185-c72e-681efe30a0e4.png">

**Angular10.2.3**
ES5サポートされなくなった代わりにデフォルトのターゲットとしてes2015が登場してきました。
modules数が増えてます
<img width="500" alt="angular10" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54858/084b1741-2e4c-5917-ed02-28911dcc54b9.png">

**Angular11.0.3**
10とあまり変わらないような気がします。
<img width="500" alt="angular11" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54858/a40ff4fa-bb16-c5cd-0cdd-bebe77b2781a.png">

これらをみてみて何かできるかというと…何ともといった印象です。


### 出力結果

以下実行した際の、ターミナルの出力結果になります。

```.sh
**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のバンドルサイズがあまり改善されているような気が正直しません…　:disappointed_relieved:

そこで
**サンプルみたいな規模が小さいものでなく、実サービスで運用しているような、もう少し規模の大きいプロジェクトではどうなるか？**
恐らくここが一番この記事で大事な所なので、こちらも各メジャーバージョン毎に計測してみました。:muscle:


#② もう少し大きめの規模のプロジェクトで計測してみる

サンプルプロジェクトではビルド速度などにあまり違いがありませんでしたが、
サンプルの 200倍 近いcode数のAngularプロジェクトに対して、大きく改善されるか確認していきます。


```.sh
-> % 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を計測してみる


#### <font color="MediumBlue">ng serve</font>

|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|


#### <font color="Teal">ng build --prod</font>

|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|<font color="DeepPink">83739 ms</font>|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|<font color="DeepPink">7.66 MB</font>|<font color="DeepPink">6.89 MB</font>|82.75 kB|1.45 kB|198.99 kB|506.62 kB|

**各バージョン毎のng buildの平均速度**
![prod_ng_build.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54858/6a98f5fa-428c-bf65-dcfa-ecb1b7b523f8.png)


ビルドに2分20秒以上(142568ms)かかっていたのが、Angular10, 11から半分の1分23秒位(83739ms)に…  :tada:
バンドルサイズのtotalも1.41MBも減りました。:blush:


### もっと改善する余地はないか？

**11.0.3**
<img width="500" alt="angular11" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54858/cb2a040d-08c9-54bb-25e9-c786a1b439ff.png">

webpack-bundle-analyzerでよくやり玉にあがってくる
moment.js周りの使用していないlocalizeが多々含まれているのでまだまだ起動時間などは改善できる余地はありそうです…
[参考:【Angular6】angular-cli を拡張してMoment.js の locale を落とし bundle サイズを削減する](https://qiita.com/MasanobuAkiba/items/72bba3404c846db76e0f)

# おわりに
個人的に、Angularのアップデートは本当に手厚くサポートされていると感じており
**[Angular Update Guide](https://update.angular.io/)**といったドキュメントや多くの**[issue](https://github.com/angular/angular/issues)**などの情報があるおかげて、コンパイルエラーにならない所までもっていくのは常に情報をキャッチアップしていればそこまで大変ではないのかなという肌感です。
※ 使用しているUIライブラリなどによっては一部正しく動かなかったりして泣きながら修正はちょこちょこしていましたが…

こういったフレームワークや言語のアップデートは
自分達のコード設計やテスト戦略とリリース戦略の見直しの一つのふり返りや、改善できる1つのポイントだと思いますし
メンテナンスを後回しにすると、新しい技術や言語の恩恵にあずかれなかったり
セキュリティ的な問題が発生した場合にサポートされなかったり…後々つけを払うことにもなりかねないと思います。

ぜひ、前向きにアップデートすることを検討できたらなと思います！


11日目は @studioTeaTwo さんです。よろしくお願いします!