Angular 5.0.0がリリースされました

Suguru Inatomi
Angular Japan User Group
14 min readNov 2, 2017

この記事はAngular公式ブログ Version 5.0.0 of Angular Now Availableを元に翻訳、加筆したものです。

Angularのバージョン5.0.0、pentagonal-donutをリリースしました。このリリースは新機能とバグ修正を含むメジャーリリースです。Angularの軽量化と高速化、そして使いやすさにフォーカスしつづけています。

ここではv5における大きな変更について取りあげます。すべてを知りたい方はチェンジログを参照してください。

Build Optimizer

5.0.0以降、CLIで作成されたプロダクションビルドではデフォルトでビルドオプティマイザが適用されるようになりました。

ビルドオプティマイザは、Angularアプリケーションのセマンティックな理解をもとにバンドルサイズを小さくするためのCLI同梱のツールです。

ビルドオプティマイザには2つの主要な仕事があります。 まず、アプリケーションの一部を pure なものとしてマークすることができます。これにより、既存のツールで提供されるTree Shaking(必要のないアプリケーションの部分を削除する機能)が改善されます。

もう1つは、アプリケーションのランタイムコードからAngularデコレータを削除することです。 デコレータはコンパイラによって使用され、実行時には不要であり、削除することができます。 これらの仕事はそれぞれ、JavaScriptバンドルのサイズを縮小し、ユーザーのアプリケーションの起動速度を向上させます。

Angular Universal State Transfer API と DOMサポート

アプリケーションのサーバー側とクライアント側のバージョン間で、アプリケーションの状態をより簡単に共有できるようになりました。

Angular Universalは、Angularアプリケーションのサーバーサイドレンダリング(SSR)を開発者が実行できるよう支援するプロジェクトです。 Angularアプリケーションをサーバー上でレンダリングし、生成されたHTMLの上でブートストラップすることで、JavaScriptをサポートしていないスクレーパーやクローラーのサポートを追加することができ、アプリケーションのパフォーマンスを向上させることができます。

5.0.0では、`ServerTransferStateModule` とそれに対応する`BrowserTransferStateModule` を追加しました。 このモジュールを使用すると、platform-serverでレンダリングの一部として情報を生成し、クライアント側に転送することで、この情報を再生成する必要がなくなります。 これは、アプリケーションがHTTP経由でデータを取得する場合などに便利です。 サーバーから状態を転送することで、アプリケーションがクライアントにそれを送信した後に、開発者が2回目のHTTP要求を行う必要がありません。 State Transfer APIに関するドキュメンテーションは今後数週間以内に公開予定です。

Angular Universalについてもう一つの変更は、Domino のplatform-serverへの追加です。 これはすなわち、サーバーサイドのコンテキスト内でより多くのDOM操作をサポートし、サードパーティ製のJSおよびコンポーネントライブラリをサポートすることを意味します。

コンパイラ改善

インクリメンタルコンパイルをサポートするようにAngularコンパイラを改良しました。 これにより、特にAOTを使用したプロダクションビルドやビルドの場合に、迅速なリビルドが可能になります。 また、デコレータに機能を追加し、空白を削除してより小さなバンドルを出力することも可能にしました。

TypeScript Transforms

内部的には、AngularコンパイラはTypeScriptのtransformとして動作し、段階的な再構築を大幅に高速化しました。 TypeScript transformは、TypeScript 2.3の一部として導入された新しい機能で、標準のTypeScriptコンパイルパイプラインにフックできるようになりました。

これを利用するには、AOTフラグをオンにして `ng serve` を実行します。

ng serve --aot

皆さんにこれを試してみることをお勧めします。 これは、CLIの将来のリリースではデフォルトになります。 現在のところ、数千ものコンポーネントを持つプロジェクトには、いくつかのパフォーマンスの問題が見つかっています。 わたしたちは、あらゆる規模のプロジェクトがこれらの改善を体験できるようにしたいと思っています。

https://angular.ioにおいてインクリメンタルなAOTビルドを実行すると、新しいコンパイラパイプラインによってビルド時間の95%が(開発マシンでは40秒以上から2秒未満に)削減されます。

わたしたちの目標は、AOTコンパイルを開発者が開発用に使用できるように十分に速くすることで、開発者が最初に本番稼動に移る際に時々起こるJITとAOTの違いを排除することでした。 チームは2秒間のインクリメンタルなAOTリビルドパフォーマンス目標を達成しました。これは、CLIの将来のリリースでデフォルトでAOTをオンにする予定です。

また、TypeScript transformへの移行の副産物として、`genDir` はもう必要なくなり、 `outDir` は変更されました:node_modules内のパッケージ用に生成されたファイルを常に出力しています。

ホワイトスペースの保持

歴史的に、テンプレートのタブ、改行、スペースは忠実に再現され、コンパイラによってビルドに組み込まれました。 今後はコンポーネントとアプリケーションにおいて、テンプレート中の空白を保持するかどうかを選択できるようになりました。

これを各コンポーネントのデコレータの一部として指定することができます。デフォルトではtrueに設定されています。

または、アプリケーション全体でtsconfig.jsonで指定することもできます。こちらも、デフォルトでtrueに設定されています。

一般に、コンポーネントレベルの指定は、アプリケーション全体の指定をオーバーライドします。 将来的にはデフォルトでfalseに設定して、開発者のためのスペースを節約したいと考えています。 <pre> タグについてはインテリジェントに処理されるので心配ありません。

`preserveWhitespaces`についての詳細はドキュメンテーションをご覧ください

Decoratorサポートの改善

デコレータの内部において、useValue、useFactory、dataの値についてラムダ式をサポートしました。 これにより、実行時にしか計算できない値をデコレータで使用できます。

名前付き関数の代わりにラムダを使うことができます。つまりd.tsやパブリックAPIに影響を与えずにコードを実行できます。

また、useValueの一部としての式も使えます。

Number, Date, Currency パイプの国際化

新しいnumber、date、currencyパイプを構築し、ブラウザ間の標準化を高め、i18nポリフィルの依存を排除しました。

Angularでは、ブラウザ組み込みのi18n APIを使用して、番号、日付、通貨の書式設定を行うためにブラウザに依存していました。これにより、ほとんどの開発者にとってポリフィルが必要になり、ユーザーがブラウザ間で矛盾した結果を見ていることが判明し、一般的なフォーマット(currencyパイプなど)が開発者の期待どおりにマッチしなかったというコメントを受けました。

5.0.0では、独自の実装を使用するようにパイプを更新しました。CLDRを使用して、サポートしたいロケールの広範なサポートと設定を提供しています。 v4とv5のパイプの動作を比較したドキュメントを作成しています。

新しいパイプの準備ができていない場合は、`DeprecatedI18NPipesModule` をインポートして古い動作にアクセスできます。

i18n パイプの詳細についてはこちらのチェンジログを参照してください。

ReflectiveInjectorからStaticInjectorへの置き換え

ポリフィルをさらに削除するために、ReflectiveInjectorをStaticInjectorに置き換えました。このInjectorにはReflect APIのポリフィルが不要になり、ほとんどの開発者にとってアプリケーションサイズが縮小されます。

Before

ReflectiveInjector.resolveAndCreate(providers);

After

Injector.create(providers);

Zoneの速度改善

デフォルトでZoneをより高速化しました。加えて、パフォーマンス重視のアプリケーションでは、Zoneを完全にバイパスすることができました。

Zoneをバイパスするには、ngZoneとして ‘noop’を使用してアプリケーションをブートストラップします。

詳細については ng-component-stateプロジェクトの例 を御覧ください.

exportAs

コンポーネント/ディレクティブの複数の名前のサポートが追加されました。これは、ユーザーに破壊的変更を与えることなく移行するのに役立ちます。複数の名前を持つディレクティブをエクスポートすると、既存のコードを破損することなくAngularのテンプレート構文で新しい名前を使用できるようになります。これは、プレフィックスの移行でAngular Materialプロジェクトの一部として使用されたもので、他のコンポーネント作成者にも役立ちます。

HttpClient

バージョン4.3では、`@angular/common`のHttpClientを、AngularでWebリクエストを行うための、より小さく、より簡単で強力な方法としてリリースしました。 新しいHttpClientは開発者から大きな賞賛を得ています。そのため、すべてのアプリケーションでHttpClientを推奨し、以前の`@angular/http`ライブラリを非推奨にしました。

HttpClientに更新するには、各モジュールのHttpModuleを `@angular/common/http` のHttpClientModuleに置き換え、HttpClientサービスを注入し、 不要になったmap(res => res.json())を削除する必要があります。

CLI v1.5

Angular CLIのv1.5から、Angular v5.0.0のサポートが追加され、デフォルトでv5プロジェクトが生成されます。

このマイナーリリースでは、デフォルトでビルドオプティマイザが有効になっているため、開発者はより小さなバンドルの恩恵を受けることができます。

また、`.tsconfig` ファイルを使用してより厳密にTypeScript標準に準拠する方法をアップデートしています。以前は遅延ロードされたルートが検出されたときや、手動で`tsconfig.json`中の`files`や`include`を更新したときに、これらのルートが自動的に追加されましたが、現在はTypeScriptの仕様に従い、これらは行いません。デフォルトでは、CLIは`files`や`include`を設定していないので、ほとんどの開発者はこの影響を受けません。

Angular FormsにupdateOn Blur / Submitの追加

すべてのinputイベントではなく、 `blur`または` submit`でバリデーションと値の更新を実行できるようになりました。

フォームは、多くのアプリケーションで非常に重要な部分です。サーバー側での検証や、実行頻度の低い検証や値の変更によって起動される重いプロセスがあれば、検証と値の変更を制御できるようになりました。 コントロール要素ごとでタイミングを変えたり、フォーム全体に対して指定することができます。

さらに、FormControlの第三引数ではなく、オプションオブジェクトに `asyncValidators`を直接指定することもできるようになりました。

テンプレート駆動フォーム

Before

<input name="firstName" ngModel>

After

<input name="firstName" ngModel [ngModelOptions]="{updateOn: 'blur'}">

または

<form [ngFormOptions]="{updateOn: 'submit'}">

リアクティブフォーム

Before

new FormGroup(value);
new FormControl(value, [], [myValidator])

After

new FormGroup(value, {updateOn: 'blur'}));

new FormControl(value, {updateOn: 'blur', asyncValidators: [myValidator]})

RxJS 5.5

使用するRxJSを5.5.2以降に更新しました。 RxJSの最近のリリースは、“lettable operators”と呼ばれる新しい方法を使って、以前のインポートによる副作用を避けるように開発者を支援します。 これらの新しいオペレーターは、オペレーターをインポートする以前の ‘パッチ’式の方法で存在していた副作用とコード分割/Tree Shakingの問題を排除します。

以前の方法

これからの書き方

さらに、RxJSはECMAScriptモジュールを使用してバージョンを配布するようになりました。新しいAngular CLIはデフォルトでこのバージョンを採用し、バンドルサイズを大幅に節約します。しかし、Angular CLIを使用していない場合でも、新しいディストリビューションを指し示す必要があります。これについてのドキュメントは、lettableオペレータのドキュメントのBuild and Treeshakingセクションにあります。

新しいRouterライフサイクルイベント

Routerに新しいライフサイクルイベントを追加し、ガードの実行開始からアクティベーションの完了までルータのサイクルを追跡できるようにしました。これらのイベントは、子ルートが更新されているときに特定のrouter-outletにスピナーを表示したり、ガードやリゾルバーのパフォーマンスを測定したりするために使用できます。

新しいイベントは順番に `GuardsCheckStart`、`ChildActivationStart`、`ActivationStart`、`GuardsCheckEnd`、`ResolveStart`、`ResolveEnd`、`ActivationEnd`、`ChildActivationEnd`です。これらのイベントを使用してスピナーを開始/停止する例は、次のようになります。

どのように更新するのですか?

Angular Update Guideはみなさんがアップデート作業を開始する前に、コードに加えたい変更、アプリケーションをアップデートする手順、および今後のAngularバージョンへの準備についてガイドします。

v5ではこれまでに非推奨にされた多くのAPI(`OpaqueToken`のような)を削除し、いくつかのAPIを新しく非推奨にしました。このガイドでは、アプリケーションに加える必要がある変更について説明します。

既知の問題

プロダクションビルドにおけるソースマップには既知の問題があります。一部のソースマップでは、エラーの原因が不明です。

https://github.com/angular/angular/issues/19840

--

--

Suguru Inatomi
Angular Japan User Group

a.k.a. lacolaco / Google Developers Expert for Angular / ng-japan organizer