Angular 17の新機能と変更点を紹介。新生Angularを体感する!

Angular 17の新機能と変更点を紹介。新生Angularを体感する!

2023年11月8日に待望のAngularバージョン17がリリースされた。

今回のアップデートはAngular 2のリリース以降もっとも大きな変更を複数含んでおり、新生Angularのプレビューバージョンの意味合いが強い。

また、大幅なパフォーマンスの改善やサーバーサイドレンダリングの強化など、今までAngularの弱点と思われていた部分をカバーするようなアップデートも多く、今後のJSフレームワークの選定にも大きくインパクトを与えるだろう。

現役でAngularを使用する開発者の人はもちろん、プロマネやアーキテクチャの人にもぜひ目を通しておいてほしい。

Angular 17のアナウンス(英語)
https://blog.angular.io/introducing-angular-v17-4d7033312e4b

Angular 17のアップデート内容

Angular 17はGoogleが”Angular’s Renaissance”表現する通り、多くの重要なアップデートを含んでいる。

おもな新機能と変更点は以下の通りだ。

  • 新しい制御フロー(@if・@for・@switch)
  • 遅延ロードビュー(Deferrable views)
  • サーバーサイドレンダリングの強化
  • ビルドシステムの変更(Vite & esbuild)
  • 開発者ドキュメントの刷新

また、Angularのロゴも新しくなった!

新しい制御フロー(@if・@for・@switch

今回のアップデートの中で、開発者にとって一番影響の大きいのがこの新しい制御フローだ。

現時点ではまた開発者プレビューの段階だが、今までのAngularのイメージを一新するような大きな変更・改善なのでチェックしてほしい

ちなみに制御フローとは、プログラミングの流れを制御する構文の事であり、今までの「ngIf」や「ngFor」の事と言えばわかりやすいだろう。

@if

まずはもっともよく使うif構文を見ていこう。

Angularの既存のif構文は以下のように複雑であり、Angularを長く使用している開発者ですら、時おりドキュメントを参照する必要があった。

<div *ngIf="isNewUser; else existingUser">
  <registration />
</div>
<ng-template #existingUser>
  <login />
</ng-template>

上記のコードは@ifを使用すれば、以下のようにシンプルに記述できる。

@if (isNewUser) {
  <registration />
} @else {
  <login />
}

@switch

次にswitch構文を見てみよう。

<div [ngSwitch]="mediaType">
  <photo *ngSwitchCase="'PHOTO'"/>
  <video *ngSwitchCase="'VIDEO'"/>
  <rich-text *ngSwitchDefault/>
</div>

上記のコードは@switchを使うと以下のように書き換えれる。JavaScriptのような自然で分かりやすいコードになったのが分かるだろう。

@switch (mediaType) {
  @case ('PHOTO') { <photo/> }
  @case ('VIDEO') { <video/> }
  @default { <rich-text/> }
}

@for

最後にfor構文を見ていこう。

<ng-container *ngFor="let company of companies">
  {{ company.id }}
  {{ company.name }}
</ng-container>
<ng-container *ngIf="companies.length === 0">
  No company found.
</ng-container>

上記のコードを@forを使って書き換えると以下のようになる。

文の先頭に@forが来たことによってより素早くテンプレートの構造を理解できる。

@emptyを使えば、配列が空であった場合の処理を簡単に記述することができる。

@for (company of companies; track company.id) {
  {{ company.id }}
  {{ company.name }}
} @empty {
  No company found.
}

新しい制御フローは記述がわかりやすくなっただけでなく、処理速度も大幅にアップしている。

興味のある人はリンクからベンチマークを確認してみよう。

遅延ロードビュー(Deferrable views)

次に紹介するのは遅延ロードビュー(Deferrable views)だ。

これはテンプレート内の一部のコンポーネントとその依存関係にあるモジュールを遅延読み込みさせるための機能であり、ページの読み込みにおけるユーザのストレスを最小限に留めるための機能だ。

こちらの機能もまだ開発者プレビューの段階だが、非常に役に立つ機能なので今のうちにチェックしておいてほしい。

blog.angular.ioより引用

使い方は非常に簡単で@deferで目的のコンポーネントを囲むのみだ。

@defer {
  <user-list />
}

トリガーの指定 Trigger

遅延可能ビューでは読み込み処理のトリガーを簡単に指定できる。

@defer (on timer(500ms)) {
  <user-list />
}

以下はトリガーのリストだ、whenはカスタムトリガーとして使用することができる。

トリガ-説明
on viewportコンポーネントがビュー領域に入った時
on idleブラウザーがアイドル状態に入った時
on interactionクリックやキーイベントが発生した時
on hoverマウスカーサーやフォーカスイベントが発生した時
on immediateレンダリングが終了した時
on timer(<time>)設定した時間が経過した時
when <expr>booleanがtrueになった時

なお、複数のトリガーをOR条件として指定することも可能だ。

@defer (on timer(500ms); when isDialogOpen) {
  <user-list />
}

事前読込み prefetsch

遅延ロードビューでは、ロードが発生する前にコンポーネントの読み込みを発生させることもできる。

@defer (on viewport; prefetch on idle) {
  <user-list />
}

プレースホルダ placeholder

さらに遅延ロードビューでは、プレースホルダやロード中の代替要素を簡単に指定することができる。

以下の例では、ロードが始まるまではプレースホルダが代わりに、ロード中にはテキストが表示される。

@defer {
  <user-list />
} @placeholder {
  <img src="user_image.png" />
} @loading {
  Loading...
}

サーバーサイドレンダリングの強化

Angularチームが近年開発に力を入れているのがSSR(サーバーサイドレンダリング)の分野だ。

シングルページアプリケーション(SPA)にサーバーサイドレンダリングの機能を盛り込んだフレームワークとしてはNext.jsが有名だが、Angularはそれらのフレームワークと比較して遅れを取っていた。

非破壊ハイドレーション(Non-destructive Hydration)

Angular 17より非破壊ハイドレーション(Non-destructive Hydration)が安定版となる。

Angular 16以前は、サーバーサイドで生成されたビューはロードが発生する度に1から生成し直す必要があった。

非破壊ハイドレーションでは、レンダリングし直す部分のみをDOMに追加するので、サーバーサイドレンダリングにおけるパフォーマンスが飛躍的に向上した。

SSRパッケージの標準化

以前は”Angular Universal”に含まれていたSSR(サーバーサイドレンダリング)が通常のAngular CLIパッケージに移動した。

既存のプロジェクトでSSRを使用する場合は以下のコマンドを使用する。

ng add @angular/ssr

ビルドシステムの変更(Vite and esbuild)

Angular 17から標準のビルドシステムがViteとesbuildに変更された。

これによりプロジェクトのビルドに掛かる時間が大幅に短縮された。

開発者ドキュメントの刷新

今回のアップデートを機にAngularの開発者ドキュメントも刷新された。

Angular公式ドキュメント: https://angular.dev

チュートリアルも付属しているので、Angular入門者にも優しい作りとなっている。

ドキュメンテーション自体がウェブコンテナーを使った、モダンでインタラクティブなウェブコンポーネントのサンプルとなっている。

その他の変更点

その他、開発者の人には知っておいてほしい変更点をここにまとめる。

signalの安定版

“signal”はAngularのために作られた、オブザーバーデザインパターンのライブラリだ。

今までAngularで使われてきた”Observable”がプッシュ型で状態の変化を通知したのに対し、Siganlはプル型で状態変化を受け取る。

Signalについては、いずれ他の記事で詳しく紹介したいと考えている。

スタンドアローンコンポーネントの標準化

Angular 14にて導入されたスタンドアローンコンポーネントがAngular 17からは標準となっている。

“ng generate component”コマンドを使って新しいコンポーネントを作成する場合は、自動的にそのコンポーネントがスタンドアローンとなるので注意しよう。

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CommonModule, RouterOutlet],
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
}

もちろん従来のモジュールは引き続き使用することができる。

新しいLifecycle Hooksの追加

Angular 17では、新しいAngular Lifecycle Hooksが追加された。

追加されたのは以下の2のLifecycle Hooksだ。

  • afterRender – アプリケーションのレンダリングを終了するたびに呼び出される。
  • afterNextRender – 次にアプリケーションがレンダリングされた時に呼び出される。
constructor() {
  afterNextRender(() => {
    console.log('called afterNextRender!!');
  }, {phase: AfterRenderPhase.Write});
}

スタイルシートの設定 styleUrl

Angular 17からコンポーネントの宣言部分において、スタイルシートを指定する方法として”styleUrls”の他に”styleUrl”が使用できるようになった。

元々、複数のスタイルシートをひとつのコンポーネントに適応することは少なかったので、若干
TSファイルの記述をスッキリさせることができる。

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CommonModule, RouterOutlet],
  templateUrl: './app.component.html',
  styleUrl: './app.component.css'
})