次世代レンダリングエンジン「Ivy」が正式リリース
「Ivy」は、Angularの次世代レンダリングエンジンで、Angular 8で設定変更により利用できるようになっていましたが、Angular 9ではIvyがデフォルトで有効になりました。
[補足]Angular 9のプロジェクトでIvyを無効にする方法
Angular 9のプロジェクトでIvyを無効にするには、tsconfig.app.jsonファイルにリスト3の通り「"enableIvy": false」の設定を記述します。
{ (略) "angularCompilerOptions": { "enableIvy": false // Ivyを無効にする設定 } }
Ivyは開発者にさまざまな利点や新機能を提供します。以下、そのいくつかを紹介していきます。
ファイルサイズの縮小
Ivyのコンパイラーは、利用しないAngularの機能をコンパイル時に除外する機能(いわゆるtree-shaking)により、生成されるコンポーネントのコードをより縮小できます。縮小の程度は状況により異なりますが、公式ドキュメントでは、小規模なアプリで30%、大規模なアプリでは25~40%の縮小をうたっています。
例えば、Angular 8のAngular CLIで生成したプロジェクト(p002-basic)と、それをAngular 9にアップデートしたプロジェクト(p002-basic-updated)で「ng build --prod」コマンドでリリース用のビルドファイルを生成してサイズを比較すると、Ivyを利用したAngular 9でサイズが縮小されていることがわかります。
デバッグに利用できる「ng」変数
開発モードでAngularを実行する場合、デバッグ機能を提供する「ng」変数が、Webブラウザーの開発者ツールで利用できるようになりました。
利用例を図4に示します。「ng serve」コマンドで実行したAngularのWebページで開発ツールを開いて、コンポーネントに対応したHTML要素(「app-root」)を選択後、JavaScriptコンソールでコンポーネントを参照する「ng.getComponent($0)」を実行すると、Angularのコンポーネントを取得して内容を確認できます(1)。ここで「$0」は、選択したHTML要素を表します。(2)で変数の内容を変更した後、「ng.applyChanges($0)」を実行すると、コンポーネントの変更検知機能を実行して、変更した変数を画面に反映します(3)。
ng変数で使用できるメソッドの一覧は公式ドキュメントを参照してください。
CSSクラス/スタイルのバインディングに関する改善
従来、コンポーネントにスタイルやクラスを複数設定した場合、それらはお互いを破壊する場合がありましたが、Ivyでは適切にマージされます。
例として、Angular 8で、複数のスタイルを設定したリスト4のコンポーネントを実装します。style属性を利用したCSSの色設定と、[style.color]を利用した、Angularのデータバインディングによる色設定を両方行っています。
<h1 [style.color]="templateStyleColor1" style="color:red"> Angular 8:色設定の例 </h1>
この場合、[style.color]に対応するtemplateStyleColor1変数に基づいた色で表示されますが、templateStyleColor1変数が未設定(undefined)の場合は、style属性の設定(赤色)を無視して黒色で表示します。
一方、Angular 9では、複数のCSSクラスが適切にマージされます。図6のサンプルで説明します。
図6のコンポーネント実装をリスト5に示します。Angular 9では、[style.color]に変数をバインディングする形式(1)の記述のほか、[style]に変数を含むJavaScriptオブジェクトをバインディングする形式(2)の記述も可能です。各設定は、(1)が最も優先順位が高く、(2)(3)の順で低くなります。(1)のtemptemplateStyleColor1がundefineの場合は(2)のtemplateStyleColor2の色指定が有効になり、templateStyleColor2もundefineの場合は(3)の色設定が有効になります。
<h1 [style.color]="templateStyleColor1" ...(1) [style]="{color: templateStyleColor2}" ...(2) style="color:red"> ...(3) Angular 9:色設定の例 </h1>
優先順位の詳細は、公式ドキュメントを参照してください。
テンプレートのより厳密な型チェック
Angular 9では、テンプレートに対するビルド時の型チェックが厳密になりました。リスト6のサンプルで説明します。(1)(3)のcanFoldはクラスに存在しないプロパティ、(2)のcarrierはコンポーネントに存在しないプロパティです。詳細はサンプルコードを参照してください。
<h1>iPhone</h1> <div> <h3>{{ iPhone.name }} </h3> <div>重量: {{ iPhone.spec.weight }}g</div> <div>5G対応: {{ iPhone.spec.is5G }}</div> <div>折り畳み(存在しない): {{ iPhone.canFold }}</div> <!--(1)--> </div> <h1>Android</h1> <div *ngFor="let phone of androidPhones"> <div>事業者(存在しない):{{ carrier }}</div> <!--(2)--> <h3>{{ phone.name }} </h3> <div>重量: {{ phone.spec.weight }}g</div> <div>5G対応: {{ phone.spec.is5G }}</div> <div>折り畳み(存在しない): {{ phone.canFold }}</div> <!--(3)--> </div>
Angular 9では、検証の厳密性設定を、tsconfig.jsonにリスト7の通り記述します。
"angularCompilerOptions": { "fullTemplateTypeCheck": true, // ...(1) "strictTemplates": true // ...(2) }
リスト7(1)(2)の両方をfalseにすると、一番厳密性が緩い「Basic mode」となります。この場合は、クラスに存在しないプロパティであるリスト6(1)がチェックされてエラーになりますが、*ngForで埋め込まれるビューの内容はチェックされないため、リスト6(2)(3)はエラーになりません。
リスト7(1)のfullTemplateTypeCheckをtrueにすると、「Full mode」でチェックを行います。Basic modeのチェックに加えて、*ngForで埋め込まれるビューの内容がチェックされるため、リスト6(1)に加えて(2)もエラーになります。ただし、*ngForの内部で参照されるphone変数は型チェックされないため、リスト6(3)はエラーになりません。
リスト7(2)のstrictTemplatesをtrueにすると、最も厳密なチェックを行う「Strict mode」になります。Basic modeとFull modeのチェックに加えて、*ngForの内部で参照されるphone変数の型チェックを行うため、リスト6(1)~(3)すべてがエラーとして検出されます。
テンプレートの型チェックモードについては、公式ドキュメントに詳細が説明されています。
わかりやすいビルドエラー
Ivyでは、ビルドエラーがよりわかりやすく表示されるようになりました。存在しないコンポーネントを参照する、リスト8の例で説明します。
<h1>{{ title }}</h1> <dummy-component></dummy-component><!-- 存在しないコンポーネント -->
Ivyを無効にしてビルドを実行すると、図7の通りエラーが表示されます。
Ivy有効時のビルドエラーは図8の通りです。エラーが発生したファイル名や行番号が表示され、該当箇所にジャンプできるようになっています。
速度の向上とAOTビルドのデフォルト化
Ivyの導入により、国際化に関する処理が最大10倍になるなど、ビルドの速度が大幅に向上しました。そのため、HTMLやTypeScriptの実装を事前にすべてJavaScriptに変換するAhead-of-Time(AOT)ビルドが、開発モード(「ng serve」実行時)でも有効になりました。単体テストを行うTestBedの速度も、40~50%程度向上するとされています。