Angular 11の新機能
以下では、Angular 11で導入された主な新機能を紹介していきます。
Webフォントのインライン展開
Webフォントを利用すると、図4のように、インターネット上に公開されたフォントを参照してWebページ内の文字に設定できます。
![図4:Webフォントを利用するサンプル(p003-inline-font)](http://cz-cdn.shoeisha.jp/static/images/article/13349/13349_004.png)
図4のサンプルでは、index.htmlでリスト6の通りWebフォントを参照しています。
<link href="https://fonts.googleapis.com/css2?family=Nerko+One&display=swap" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Sawarabi+Mincho" rel="stylesheet">
Angular 11では、Webフォントの表示速度を向上するため、「ng build --prod」コマンドで本番用のビルドを行うと、リスト6の記述を図5の通りインライン展開します。
![図5:Angular 11がインライン展開したWebフォント指定(p003-inline-font)](http://cz-cdn.shoeisha.jp/static/images/article/13349/13349_005.png)
インライン展開の有無は、angular.jsonの「optimization」オプションで、リスト7の通り設定できます。フォントのほかにJavaScriptとCSSの最適化も併せて設定できます。プロジェクト生成時のデフォルト設定は(1)で、すべての最適化が有効になっています。
// スクリプト、CSS、フォントの最適化を一括で設定する場合 ...(1) "optimization": true, // スクリプト、CSS、フォントの最適化を個別に設定する場合 ...(2) "optimization": { "scripts": true, "styles": true, "fonts": true },
Component Test Harnessの対応範囲拡大
Component Test Harnessは、単体テストの記述時に、HTMLの記述や構造変更の影響を受けずにAngular Materialのコンポーネントを操作できる「ハーネス」を提供する仕組みで、Angular 9から導入されました。Angular 11では、すべてのAngular MaterialコンポーネントでComponent Test Harnessが利用できるようになりました。
ここではComponent Test Harnessの利用方法を、図6のサンプルで説明します。メーカーのボタンをクリックすると、そのメーカーのスマートフォン名を画面に表示します。
![図6:Component Test Harnessを利用するサンプル(p004-test-harness)](http://cz-cdn.shoeisha.jp/static/images/article/13349/13349_006.png)
「ng test」コマンドで単体テストを実行すると、Chromeブラウザーが起動してテストが実行され、図7の通り表示されます。ここでは「iPhone12」の名称が誤り(「iPhone」の次にスペースが必要)のため、Appleボタン押下時のテストがエラーになります。
![図7:単体テストの実行結果(p004-test-harness)](http://cz-cdn.shoeisha.jp/static/images/article/13349/13349_007.png)
図7の単体テスト記述は、リスト8の通りです。
describe('AppComponent', () => { let component: AppComponent; // テスト対象のコンポーネント let loader: HarnessLoader; // ハーネスのローダー ...(1) beforeEach(async () => { (略) // fixtureから、テストするコンポーネントを生成 let fixture = TestBed.createComponent(AppComponent); component = fixture.componentInstance; // fixtureから、ハーネスのローダーを生成 ...(2) loader = TestbedHarnessEnvironment.loader(fixture); }); // Appleボタンクリック時 ...(3) it('Apple button clicked', async() => { // phoneの初期値は空文字 expect(component.phone).toBe(''); // コンポーネント内の最初のMatButtonに対するハーネスを取得 ...(4) const firstButton = await loader.getHarness(MatButtonHarness); // ボタンをクリック ...(5) await firstButton.click(); // phoneの内容を確認 expect(component.phone).toBe('iPhone 12'); }); (略) });
(1)はハーネスを取得するためのローダーです。ローダーはAppComponentに対応するfixtureをもとに、(2)のloaderメソッドで生成します。単体テストの処理(3)では、(4)のloader.getHarnessメソッドに、Angular Materialコンポーネントのハーネスクラス(ここではMatButtonに対応するMatButtonHarness)を渡してハーネスを生成します。生成したハーネスには、対象のAngular Materialコンポーネントを操作できるメソッドが定義されており、ここでは(5)のclickメソッドでボタンをクリックしています。
なお、リスト8(4)ではAppComponent内の最初のボタンに対するハーネスを取得していますが、リスト9の通り、さまざまな指定方法でハーネスを取得できます。詳細はサンプルコードを参照してください。
// コンポーネント中のすべてのMatButtonに対するハーネスを取得 const buttons = await loader.getAllHarnesses(MatButtonHarness); ---- // コンポーネント内で、テキストが「SHARP」のボタンに対するハーネスを取得 const sharpButton = await loader.getHarness(MatButtonHarness.with({ text: 'SHARP' })); ---- // コンポーネント内で、IDが「btn-sony」のボタンに対するハーネスを取得 const sonyButton = await loader.getHarness(MatButtonHarness.with({ selector: '#btn-sony' }));
開発効率をアップするHot Module Replacement
「ng serve」で実行されるAngularの開発用Webサーバーでは、ソースコードを変更するとブラウザーがリロードされて変更が反映されますが、このときにフォームの入力内容などの画面状態が消えてしまいます。
Angularでは、画面状態を保持しつつモジュールを動的に変更するHot Module Replacement(HMR)が従来から利用できましたが、利用には設定やコードを変更する必要がありました。Angular 11では、「ng serve --hmr」を実行することで、設定やコードを変更することなくHMRを有効にできます。
図8は、入力された名前をもとにあいさつ文を表示するサンプルです。HMRを利用しない場合、コードの「こんにちは」を「こんばんは」に変更すると、入力された名前が消えてしまいますが、HMR利用時は、入力された名前を維持しつつ、コードの変更がWebページに反映されます。
![図8:Hot Module Replacementの動作(p005-hmr)](http://cz-cdn.shoeisha.jp/static/images/article/13349/13349_008.png)
TSLintからESLintへ
Angularでは、Lint(ソースコードの形式チェック)を行うのにTSLintを利用していました。しかし、TSLintは開発者によって非推奨とされ、ESLintへ移行するように案内されています。
これを受けてAngular 11ではTSLintが非推奨になり、ESLintへ移行する方法が提供されています。リスト10のサンプルで移行例を説明します。このコードは(1)〜(3)の箇所でLintのエラーが表示されます。
lintErrorFunc(): void { // ★文字列は「"」ではなく「'」を利用するべき ...(1) // ★letでなくconstを利用するべき ...(2) let greet = "ご挨拶申し上げます"; // ★行末のセミコロンがない ...(3) console.log(greet) }
リスト10のコードに対して「ng lint」でLintを実行すると、TSLintでチェックが行われてエラーが表示されますが、TSLintが非推奨であるメッセージも表示されます。
![図9:TSLintによるソースコードチェック結果(p006a-tslint)](http://cz-cdn.shoeisha.jp/static/images/article/13349/13349_009.png)
このプロジェクトをESLintに移行するには、リスト11のコマンドを実行します。(1)で移行の処理を行うSchematicsをインストールして、(2)でそれを実行します。コマンドの最後に指定している「p006-eslint」は、移行するプロジェクト名です。
ng add @angular-eslint/schematics #...(1) ng g @angular-eslint/schematics:convert-tslint-to-eslint p006-eslint # ...(2)
移行後に「ng lint」でLintを実行すると、図10の通りESLintでチェックが行われます。
![図10:ESLintによるソースコードチェック結果(p006-eslint)](http://cz-cdn.shoeisha.jp/static/images/article/13349/13349_010.png)