ビルドが100倍速くなると噂の Angular 17 の新ビルドシステムを使ってみた

先月、Angular の新バージョンである Angular 17 が公開されました。
新しいコードフローやビルドシステムが追加されたり、Signalが安定版になったりと機能面で大きく進化しました。
また、ロゴの変更やAngularを実行できるサンドボックス機能を搭載した新たなドキュメントサイトが公開されるなど、ブランディング面でも大きな変更がありました。

そんな Angular 17 ですが、どうやら新しいビルドシステムがだいぶ速いらしいと巷で噂になっていたので実際に検証してみました。

## 色々ある Angular のビルドシステム
Angularにはクライアントサイドレンダリング（CSR）用やサーバーサイドレンダリング（SSR）用など、複数のビルダーが存在します。

#### Angular のビルダー
| ビルダー | 説明 |
|:-:|:-:|
| @angular-devkit/build-angular:browser | CSR用のビルダー|
| @nguniversal/builders:dev-server  | CSR用の開発サーバー  |
| @nguniversal/builders:ssr-dev-server  | SSR用の開発サーバー  |
|@angular-devkit/build-angular:browser-esbuild|esbuild で動作するCSR用のビルダー<br>Angular 14から追加され、長らく開発者プレビューだった|
|@angular-devkit/build-angular:application|esbuildで動作するCSRとSSR用のビルダー<br>Angular 17から追加され、CSRとSSRの両方で使える<br>Angular 17 からはこれがデフォルトになる |
|@angular-devkit/build-angular:ng-packagr	|Angular Package Formatに準拠したAngularライブラリ用のビルダー|

これらのうち、`browser-esbuild`と`application`には esbuild が、それ以外には webpack が使われています。
これまでは CSRのビルドでしか esbuild を使えませんでしたが、Angular 17 で追加された `application` ビルダーを使うことで、SSRのビルドにも esbuild が使えるようになりました。

これからはこのビルダーがAngularのデフォルトになります（従来の webpack を用いたビルドがなくなるわけではないそうです）

webpack から esbuild に変わったことで、ビルド時間が大幅に短縮されました。
両者について簡単に説明すると、

### webpack  とは
webpackは複数のJavaScriptファイルを一つのファイルにまとめて出力するツールです。
クライアント開発では最も有名なモジュールバンドラーのひとつです。
長らくモダンフロントエンド開発を支えてきましたが、近年では設定ファイルの複雑さやパフォーマンスがネックになり、他のモジュールバンドラーにシェアを奪われつつあります。

https://webpack.js.org/


### esbuild  とは
webpackと同じモジュールバンドラーのひとつ。
Go言語で書かれているため、高速に動作するのが特徴。
公式曰く、webpack の 10 から 100 倍速いとのこと。

https://esbuild.github.io/


<br>
どちらもモジュールバンドラーという複数のソースをまとめてくれる、モダンフロント開発ではなくてはならないツールのひとつです。

この界隈では長年 webpack が人気でしたが、設定ファイルの複雑さやパフォーマンスの問題などから、近年はそれらを解決した新たなモジュールバンドラーが多く登場するようになりました。

![スクリーンショット 2023-12-04 1.27.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3620651/0451b0bc-1bfd-941f-0a3a-0eb57c1a7bdd.png)
https://npmtrends.com/esbuild-vs-rollup-vs-vite-vs-webpack

esbuild もそのうちのひとつとなります。
esbuild の速さの秘密については色々なサイトで説明されているのでそちらをご参照ください。

https://qiita.com/GS-AI/items/c313973463bb552934e9

https://zenn.dev/highgrenade/scraps/6ec19412247b87


## @angular-devkit/build-angular:application の使い方
さて、そんな esbuild が Angular 17 からは標準で使えるようになりました。
しかし、既存のシステムで新しいビルドシステムを使用するためには、いくつか手順が必要です。

手順を確認しながら従来のビルダーとのパフォーマンス検証を行っていきましょう。

ちなみに、必要な手順は公式ドキュメントに記載されています。

https://angular.dev/tools/cli/esbuild



### 前提： Angular 17 以上であること
まずは　Angular 17 までアップデートしましょう。

https://update.angular.io/?l=3&v=16.0-17.0

### 使用手順
#### 1. angular.json の `builder` を変更する
これを
```json
...
"architect": {
  "build": {
    "builder": "@angular-devkit/build-angular:browser",
...
```
こうする
```json
...
"architect": {
  "build": {
    "builder": "@angular-devkit/build-angular:application",
...
```

#### 2. ビルドターゲットのオプションを変更する
angular.json のビルドターゲットのオプションのうち、以下のパラメータを変更します。

* `main` を `browser` に変更する。
* `polyfills`を単一のファイルではなく、配列にする。
* `buildOptimizer`を削除する。
* `resourcesOutputPath`を削除する。
* `vendorChunk`を削除する。
* `commonChunk`を削除する。
* `deployUrl` を削除する。代わりに `<base href>` を使用する。詳細は公式の[デプロイメントドキュメント]( https://angular.dev/tools/cli/deployment#--deploy-url)を参照。
* `ngswConfigPath` を `serviceWorker` に変更する。


<br>
SSRを使用していない場合はこれで準備完了です。
SSRを使用している場合はさらにSSR用のコードを変更する必要があります。
詳細はAngularの公式ドキュメントをご参照ください。

https://angular.dev/guide/ssr

#### 3. ビルドする
いままでと同様に `ng build` でビルドできます。


## 実際にビルドしてみた結果
|ビルド回数|旧 (webpack) | 新 (esbuild) |
|:-:|:-:|:-:|
|1回目| 47.371 sec  |  17.158 sec |
|2回目| 17.801 sec  |  16.347 sec |
|3回目| 14.474 sec  |  16.480 sec |
|ビルドサイズ|5.06 MB     |5.01 MB      |

さすがに１００倍とはなりませんでしたが、キャッシュがない状態での初回ビルドの時間が大幅に短縮されました。
2回目以降はキャッシュが効くため webpack とさほど変わらない結果となりました。
また、ビルドサイズもあまり変わりありません。

## おわりに
今回の高速化は webpack から esbuild に変わったことがほとんどの理由です。
そのため、既に `@angular-devkit/build-angular:browser-esbuild`を使用している場合は、`@angular-devkit/build-angular:application`に変えてもここまで速くはなりません。
webpak を使用している方やSSRでビルドしている方は、かなり効果が期待できますので Angular 17 にアップデートすることをおすすめします。