はじめに
Angular v22 へアップデートしたタイミングで、テストランナーを Karma から Vitest に移行しました。その作業の中で、angular.json のビルダー指定を @angular-devkit/build-angular から @angular/build に変える必要がありました。
@angular-devkit/build-angular
@angular/build
手順どおりに書き換えれば動くのですが、名前が似ているせいで何が置き換わったのかピンときませんでした。
「この2つ、何が違うの? 両方必要なの?」
なんとなく書き換えて終わりにするのも気持ち悪かったので、公式ドキュメントを読んで整理しました。
結論から言うと
@angular/build が現行の公式ビルドシステムのパッケージで、@angular-devkit/build-angular はwebpack ベースの従来ビルダーを抱えた旧来のパッケージです。
並列の選択肢ではなく、世代が違うものだと理解すると腑に落ちました。
それぞれの正体
@angular/build
npm 上の説明は「Official build system for Angular」。ビルドに esbuild、開発サーバーに Vite を使う新しいビルドシステムを収めたパッケージです。
新しいビルドシステム自体は Angular v17 から提供されていて、公式の移行ガイドも「In v17 and higher」という書き出しになっています。@angular/build という独立したパッケージが追加されたのは v18 で、CLI のリリースノートに「新しい公式ビルドシステムのパッケージを導入」として記載されています。
なお、Vite については誤解しやすい点があります。公式ドキュメントには、Angular CLI における Vite の利用は現状開発サーバーとしての役割に限定されている、と明記されています。開発ビルドは Angular 側のビルドシステムがメモリ上に生成し、その結果を Vite に渡して配信する構成です。アプリケーションのバンドル自体を Vite が行っているわけではありません。ただし、サードパーティ依存のプリバンドルには Vite の機能が使われています。
@angular-devkit/build-angular
Angular CLI が昔から使ってきた Architect ビルダーの詰め合わせです。
現在この npm ページを見ると、こんな注意書きが出ています。
Angular's Webpack support is deprecated. Use the esbuild and Vite-based "@angular/build" package instead
Angular の webpack サポートは非推奨で、esbuild と Vite ベースの @angular/build を代わりに使ってください、という内容です。
2つは並列ではなく、依存関係でつながっている
ここが一番わかりにくかったところです。
npm の依存ツリーを見ると、@angular-devkit/build-angular が @angular/build に依存しています。つまり前者を入れると後者も一緒に入ってきます。
@angular-devkit/build-angular
└─ @angular/build ← 依存している
@angular-devkit/build-angular は、現在 @angular/build に依存しつつ、従来の webpack ベースのビルダーと移行用の互換ビルダーを提供しているパッケージ、という位置づけです。
ただし、@angular-devkit/build-angular のすべてが @angular/build の薄いラッパーになっているわけではありません。browser などは build-angular 側に独自の実装を持っています。
どのビルダーがどっちに入っているか
v22 の公式ドキュメントでは、ng build の build ターゲットに使うビルダーとして次の4つが挙げられています。
-
@angular/build:application— esbuild でクライアントバンドル・Node サーバー・ビルド時プリレンダリングをまとめてビルドする -
@angular-devkit/build-angular:browser-esbuild— esbuild でクライアント側のみバンドルする -
@angular-devkit/build-angular:browser— webpack でクライアント側のみバンドルする -
@angular/build:ng-packagr— Angular Package Format に沿ってライブラリをビルドする
ng new で生成したアプリケーションは @angular/build:application を、ng generate library で生成したライブラリは @angular/build:ng-packagr をデフォルトで使います。
@angular/build 側には他にも dev-server、extract-i18n、karma、unit-test などが入っています。開発サーバーの設定例も、公式ドキュメントでは @angular/build:dev-server の形で書かれています。
"serve": {
"builder": "@angular/build:dev-server",
"options": {
"prebundle": {
"exclude": ["some-dep"]
}
}
}
一方、@angular-devkit/build-angular 側に残っている旧来・互換系の代表的なビルダーは次のあたりです。
-
browser— webpack ベースの従来ビルダー -
server/ssr-dev-server/app-shell/prerender— SSR やプリレンダリング関連の旧ビルダー -
browser-esbuild— 移行用の互換ビルダー
ただし、@angular-devkit/build-angular が公開しているのはこれだけではありません。application や dev-server、extract-i18n、karma、ng-packagr も @angular-devkit/build-angular:* の名前で引き続き提供されています。たとえば application は @angular/build:application への alias です。つまり @angular-devkit/build-angular:application と書かれていても、実際に動いているのは @angular/build 側の実装ということになります。
もうひとつ注意したいのが browser-esbuild です。名前のとおり esbuild ベースなので、「@angular-devkit/build-angular に残っているもの = webpack 由来」とは言い切れません。公式ドキュメントでは、既存の browser ビルダーからの変更を最小限にするための互換ビルダー(compatibility builder)として説明されています。application への移行が難しいプロジェクト向けの選択肢という位置づけです。
app-shell / prerender / server / ssr-dev-server については、これらの機能を application ビルダーが統合して持っているので、application に移行するとまとめて不要になります。
テストビルダーまわり
@angular/build:unit-test は @angular/build 側にあるビルダーです。
Angular v21 以降、新規プロジェクトのデフォルトのテストランナーは Vitest になっていて、ng new の test-runner オプションのデフォルトも Vitest です。Karma も引き続きサポートされていて、ng new my-app --test-runner=karma で選べます。
既存プロジェクトを Karma から移行する場合は、angular.json の test ターゲットのビルダーを差し替えます。
"test": {
"builder": "@angular/build:unit-test"
}
unit-test ビルダーは tsConfig が tsconfig.spec.json、buildTarget が ::development をデフォルトにしています。
注意点として、旧来の karma ビルダーは test ターゲット内に polyfills や assets、styles といったビルドオプションを直接書けましたが、unit-test ビルダーはこれをサポートしていません。テスト用のビルド設定が development 構成と異なる場合は、専用の build 構成を作ってそちらに移す必要があります。
なお、既存プロジェクトを Karma から Vitest に移行するプロセス自体は、公式ドキュメント上 experimental とされています。
自分のプロジェクトがどっちを使っているか確認する
angular.json の architect 配下を見て、build / serve / test それぞれの builder フィールドを確認します。
{
"projects": {
"my-app": {
"architect": {
"build": {
"builder": "@angular/build:application"
},
"serve": { },
"test": { }
}
}
}
}
package.json の devDependencies に @angular-devkit/build-angular が直接書かれていれば、旧パッケージを直接依存として持っている状態です。
依存を削除できるかどうかを判断する場合は、この3つだけでなく architect 配下全体に @angular-devkit/build-angular: の参照が残っていないか確認します。extract-i18n や独自に定義した target から参照されている可能性があるためです。
移行はコマンド一発で走る
自動移行のスキーマティックが用意されています。
ng update @angular/cli --name use-application-builder
ng update @angular/cli に対して use-application-builder という名前の移行スクリプトを指定して実行するコマンドです。v18 から、アップデート時にこの移行が提案されるようになりました。
この移行がやってくれる内容は公式ドキュメントに列挙されていて、主なものは次のとおりです。
- 既存の
browser/browser-esbuildターゲットをapplicationに変換する - 旧 SSR ビルダーを削除する(
applicationが担当するようになるため) -
tsconfig.server.jsonをtsconfig.app.jsonにマージし、esModuleInterop: trueを追加する - webpack 固有のスタイルシート記法(
@import/url()のチルダやキャレット)を除去する - 他に
@angular-devkit/build-angularの使用箇所が見つからなければ、依存の少ない@angular/buildパッケージに切り替える
最後の項目が、今回調べたかったことの答えそのものでした。「@angular-devkit/build-angular を使う理由が無くなったら @angular/build に置き換える」という方針が、移行スクリプトの挙動として公式に組み込まれています。
なお、移行後は必ずビルドを通してみる必要があります。webpack 固有の機能に依存していた箇所で新しくエラーが出る可能性があるためです。
カスタムビルダーを使っている場合
@angular-builders/custom-webpack のようなサードパーティのカスタムビルダーを使っている場合、この自動移行の対象にはなりません。公式ドキュメントにも、カスタムビルダーを使っている場合は移行の選択肢についてそのビルダー側のドキュメントを参照するように、と書かれています。
つまり移行できるかどうかは、そのビルダーが新しいビルドシステムに対応しているかどうか次第です。
思ったこと
-
名前から関係性が読み取れない:
@angular-devkit/build-angularと@angular/buildという名前だけ見ると同格に見えますが、実際は片方がもう片方に依存している関係で、ここが一番混乱しました -
パッケージ名とバンドラーが一対一ではない:
browser-esbuildのように、旧パッケージ側にも esbuild ベースのビルダーがあります。パッケージ名だけで「こっちは webpack」と決めつけると読み違えそうです -
ng newの生成物が基準になる: 迷ったら新規プロジェクトを1つ作ってangular.jsonを見比べるのが早そうだと感じました
まとめ
-
@angular/buildは現行の公式ビルドシステムのパッケージ。ビルドは esbuild、開発サーバーは Vite。新ビルドシステム自体は v17 から、パッケージとしての追加は v18 -
@angular-devkit/build-angularは旧来のパッケージで、webpack ベースの従来ビルダーと互換ビルダーを提供している - 2つは並列ではなく、
@angular-devkit/build-angularが@angular/buildに依存している関係 -
ng new/ng generate libraryの生成物はどちらも@angular/buildのビルダーを使う -
angular.jsonに@angular-devkit/build-angular:*のビルダーが残っておらず、サードパーティパッケージからの依存もなければ、@angular-devkit/build-angularを直接依存として持つ必要はない - テスト用の
@angular/build:unit-testは@angular/build側にあり、v21 以降の新規プロジェクトは Vitest がデフォルト - 移行は
ng update @angular/cli --name use-application-builderで、パッケージの差し替えまで面倒を見てくれる
調べる前は「似たようなパッケージが2つある」としか思っていませんでしたが、依存関係とビルダーの所属が分かった時点で、angular.json の書かれ方も package.json の中身も一気に読めるようになりました。
参考になったら いいね や ストック をお願いします!
同じところで迷ったことがある方のコメントもお待ちしています。
参考
- Building Angular apps - Angular
- Angular application build system - Angular
- Migrating from Karma to Vitest - Angular
- Testing with Karma and Jasmine - Angular
- @angular/build - npm
- @angular-devkit/build-angular - npm
関連リンク
技術ブログでも学びや検証内容をまとめています。