Dev Study
← Angular コース

75. コンポーネントを追加すると何が変わるか — ビルド時の変化

ng generate component で部品を1つ作り、親の imports に書き、テンプレートに <app-user-card> と書く — この日常の操作で、ビルド成果物に何が起きるかを追いかけます。まずコンパイラは、親テンプレートに現れたタグ名を、imports に並んだ各部品の selector と突き合わせます。重要なのは、このセレクタ照合がビルド時に完了していることです。実行時のAngularがHTMLの中から <app-user-card> を検索して探し回る、という処理は存在しません。

照合が付くと、親の ɵcmp の依存リストに子コンポーネントのクラス参照が記録され、親のテンプレート関数の該当位置は「ここに子のホスト要素を作り、子を起動する」という命令になります。逆に imports への書き忘れは照合の失敗で、そのタグは「ただの未知のHTML要素」として扱われ、ビルド時に NG8001(is not a known element)エラーになります。何度も見たあのエラーの正体は、この突き合わせに相手が見つからなかった、という報告です。

バンドルへの影響も参照のつながりで決まります。ɵcmp の依存リストで参照された部品は親と同じチャンク(JSファイル)に入り、遅延ルートや @defer の境界の内側からしか参照されない部品は別チャンクに切り出されます。つまり「コンポーネントを1つ追加する」とは、ビルド時の参照グラフに節点を1つ足すことであり、どのチャンクが太るか・初期表示に響くかは、どこからその部品への参照が張られたかで決まります。パフォーマンスのセクションで学んだバンドル分析は、この参照グラフを可視化する作業だったわけです。

サンプルコード(フレームワーク環境が必要なため表示のみ)

// 追加の操作: imports に書いてテンプレートで使う
@Component({
  selector: 'app-page',
  imports: [UserCardComponent], // ← コンパイラへの照合候補の提示
  template: '<app-user-card [name]="userName()" />',
})
export class PageComponent {}

// ビルド時に起きること(概念図):
//
// 1. 照合: <app-user-card> を imports の selector と突き合わせ
//    → UserCardComponent がマッチ
//
// 2. 記録: PageComponent.ɵcmp の依存リストに
//    UserCardComponent への参照が入る
//
// 3. 命令化: テンプレート関数の該当位置が
//    「app-user-card 要素を作り、子を起動し、name を渡す」命令になる
//
// 4. バンドル: 参照でつながったので同じチャンクに同梱される
サンプルコードで身につける(5本) →

学んだ概念を、素朴な例から実務寄りの例まで5つの具体例で確認します。

公式ドキュメントで詳しく ↗