Angular 11の新機能
以下では、Angular 11で導入された主な新機能を紹介していきます。
Webフォントのインライン展開
Webフォントを利用すると、図4のように、インターネット上に公開されたフォントを参照してWebページ内の文字に設定できます。
図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の通りインライン展開します。
インライン展開の有無は、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のサンプルで説明します。メーカーのボタンをクリックすると、そのメーカーのスマートフォン名を画面に表示します。
「ng test」コマンドで単体テストを実行すると、Chromeブラウザーが起動してテストが実行され、図7の通り表示されます。ここでは「iPhone12」の名称が誤り(「iPhone」の次にスペースが必要)のため、Appleボタン押下時のテストがエラーになります。
図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ページに反映されます。
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が非推奨であるメッセージも表示されます。
このプロジェクトを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でチェックが行われます。
