Dev Study
Angular コース

34. ゾーンレスとOnPushの既定化

v22では、新しく作るアプリから zone.js が標準で外れ、ゾーンレスがデフォルトになりました。これまでAngularは zone.js を使って「何か起きたかもしれない」タイミングで画面全体を見直していましたが、ゾーンレスでは更新のきっかけをシグナルなどの明示的な変更に絞ります。これがシグナル中心への移行の総仕上げにあたります。

あわせて、変更検知の既定が OnPush になりました。OnPush のコンポーネントは「入力(input)が変わった」「シグナルが変わった」「イベントが発生した」ときだけ再描画されるため、無駄なチェックが減り、アプリが軽くなります。これまでの「常にチェックする」挙動は ChangeDetectionStrategy.Eager という名前で残っており、必要なときは明示的に指定できます。

実務上の注意は、シグナルを使わず普通のプロパティを setTimeout などの外から書き換えると、OnPush では画面が自動で更新されないことがある、という点です。だからこそ、これまでのレッスンで繰り返してきた「状態はシグナルで持つ」という方針が、v22ではいっそう自然な書き方になります。既存アプリは自動マイグレーションで Eager が付与されるため、いきなり壊れることはありません。

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

import { Component, signal, ChangeDetectionStrategy } from '@angular/core';

// v22では何も書かなければ OnPush が既定になる(下の指定は明示しただけ)
@Component({
  selector: 'app-counter',
  changeDetection: ChangeDetectionStrategy.OnPush,
  template:
    '<p>{{ count() }}</p>' +
    '<button (click)="count.set(count() + 1)">増やす</button>',
})
export class CounterComponent {
  // シグナルなので OnPush でも変更が確実に画面へ反映される
  count = signal(0);
}

// 旧来の「常にチェック」挙動が要るときだけ Eager を指定する:
//   changeDetection: ChangeDetectionStrategy.Eager
公式ドキュメントで詳しく ↗