Angular(バージョン17)の新しいコントロールフロー構文について深く探る

Angular17のリリースと共に、私はAngularのコントロールフローシンタックスについて探求し、その利点を示したいと思いました。この新しいシンタックスは、Angularのv17リリースに含まれていた他の機能群と今後見ていくものですが、これまでのAngularで行ってきたコントロールフローとは大きく異なるものであり、大変画期的なものです。

コントロールフローとは、スクリプト内でコンピュータによって実行されるステートメントの順序のことです。条件(if...else, switch ステートメント)を使って、特定の条件が満たされたときに実行するステートメントとスキップするステートメントを決定することができます。ループを使ってステートメントを繰り返し実行することもできます。

Angularのコントロールフローには新しいシンタックスが導入されており、これまでのシンタックスとは大きく異なります(旧シンタックスと呼称します)。さらに、新しいコントロールフローシンタックスは、開発者プレビューの段階まで進んでいます。

まず、新しいシンタックスと旧シンタックスを比べてみましょう。

If条件

例えば、条件が真のときにテンプレートのセクションを表示したいとしましょう。旧シンタックスでは、以下のように行っていました:

旧 if…else 条件式シンタックス in Angular

しかし今では、全く新しいシンタックスにより、以下のようになります:

新しいAngularのif…else条件式シンタックス

さらに簡略化すると以下のようになります:

Forループ

Forループに関してはどうでしょうか:

Forループ(V17前)

新しいAngularのForループシンタックス

ご覧の通り、ユニークなキーを生成するトラッキング式を渡し、DOM内での配列項目の場所との関連づけをパフォーマンス向上のために使用できます。これは新しいコントロールフローシンタックスでは必須ですが、旧シンタックスではオプションでした。

NgSwitch

こちらは旧シンタックスの一例です

そして、これが新しいシンタックスでの様子です

気付いたことがありますか?新しいシンタックスは読みやすい(主観的ですが、私たちは両方とも主観的に同意することができると思います)で、TypescriptやJavascript(または大多数の言語)を書いているときに出会う非常にお馴染みのシンタックスに似ています。Angular初心者にとって、目を細めて頭をかきむしらなければ、旧シンタックスを理解するのは難しいでしょう。

そしてもう一つの大きなメリットが、シンタックスのハイライトとフォーマットです。旧シンタックスでは、構造ディレクティブがHTML属性の一部だったため、シンタックスハイライトはあまりありませんでした。今では、コントロールフローがHTMLタグの一部ではないため、シンタックスハイライトがすでに可能です。その上、「prettier」npmパッケージ(最新バージョンに更新してください)は、新しいAngularのシンタックスのフォーマットをサポートしており、これが本当に素晴らしいです。

これらを組み合わせることで、テンプレート内でどのブロックが終わり、どのブロックが始まるのか、そしてネストされたブロックが簡単に識別できるようになります。これはコードの可読性を大きく向上させるはずです。

そして、「ng-container」と「ng-template」が条件付きHTMLブロックに不要になると、ずっとクリーンなコードが実現し、ボイラープレートも減ります。

物事がそんなにシンプルであればいいのに

ここまででifとforのシンタックスを見てきましたが、switchについてはどうでしょうか。こちらに例があります。

旧シンタックスに対する改善点

→ forループ: 必須のトラック式

新しいシンタックスでは、特に大きなリストを扱う際にパフォーマンスを向上させるため、配列の各アイテムをDOMでのビュー位置と関連づけるためのキーを生成するトラック式を提供する必要があります。

これを省略しようとすると、以下のようなエラーが表示されます:

@forループには「トラック」式が必要です

その上、Angularはforループ用の新しい最適化されたアルゴリズムを使用しているため、コレクションの変更に応じたDOM操作を最小限にして、より効率的なものになっています。

→ forループ @empty キーワード

さらに、リストが空の場合に対処するために @empty キーワードが導入されました。これは便利な機能です。

→ より読みやすいelse

先ほど見たように、Angularの旧コントロールフローシンタックスのelseはあまり読みやすくなく、たくさんのボイラープレートコードが必要でしたが、新しいコントロールフローではずっと読みやすく、特にAngular初心者にとってはより馴染みやすいです。

Asyncパイプについては?

以前のように、Observableへのサブスクライブにasyncパイプを使用することができます。

Forループ内では、こうやって達成できます:

Ifブロックでも同様に行うことができます:

納得しましたが、どうやって切り替えればいいですか?

まず、Angularプロジェクトをv17に更新したことを確認し、次に既存のコントロールフローシンタックスを新しいコントロールフローシンタックスに変換するために、以下のスキーマを実行できます。

ng g @angular/core:control-flow-migration

パスの入力を求められたら、プロジェクトのパスを入力して、それで完了です。

注意点として、Angularの大近く前進として、コントロールフローシンタックスは開発者プレビューにあることです。これは、Angularチームがセマンティックバージョニングに従わずに、一般提供される前に生じるかもしれない問題や懸念点を修正していくための柔軟性を持たせるという意味です。同じAngularの保証が全ての機能に対して提供されているとします。

Unstackedの次回: 新しい @defer シンタックス

その上で、Angularにはコンポーネント、ディレクティブ、および特定の条件までテンプレートでのパイプを遅延ロードするための新しい @defer シンタックスが導入される予定です。次回のUnstackedでこの件について詳しく説明していく予定ですが、この記事があまりにも長くなり過ぎるため、数週間以内に行います。

まとめ

この投稿では、Angularの新しいコントロールフローシンタックスと、それが古いシンタックスと比べて持つ利点について見てきました。新しいコントロールフローシンタックスは、お馴染みの感じで、旧シンタックスと比べて主観的に読みやすいものであり、何が起こっているのかを理解するのにそれほど頭を悩ませる必要がないことを学びました。また、 @empty キーワードやパフォーマンス向上のための必須のトラック式など、旧シンタックスに取って代わるだけでなく、それを改良する新しい機能を導入することも学びました。

それでは、ここまでです。次回まで学び続けましょう。

こちらの記事はdev.toの良い記事を日本人向けに翻訳しています。
https://dev.to/this-is-angular/a-deep-dive-into-new-control-flow-syntax-for-angular-17-24ld