この記事は、「ng-japan 2016」のセッションレポートです。講演内容を再現していますが、ニュアンス等伝えきれない場合があるので、気になるところは、記事末尾に掲載の講演資料やYoutube動画でご確認ください。
Angular2の失敗しない始め方 / 稲富駿氏
株式会社トップゲートの稲富 駿氏によるセッションです。セッション資料や配信動画は記事末尾でご確認ください。このセッションでは、大きく3つの点について触れられました。それぞれのポイントを書き起こします。
- Angular2に関するよくある質問や誤解について
- Angular2を構成する基礎技術について
- Angular2を学ぶために必要なこと
1. Angular2に関するよくある質問や誤解について
Angular2について正しい知識を知ってもらうために、よくある質問とその回答について幾つか取り上げる。
Q1. AngularJS2なのか?Angular2なのか?
Angular2が正しい名称。ここが大事。Angularはただ単にJSフレームワークライブラリではない。JSフレームワークであると同時に、 ElectronやNativeアプリで動くライブラリでもあり、Serverサイドで動くためのライブラリでもある。つまり、Angularはアプリケーション開発のためのプラットフォームと認識するのが正しい。
Q2. Angular2を学ぶためにTypeScriptを勉強する必要があるのか?
必ず必要というわけではないが、勉強すべきである。Angular2はコードベースがTypeScriptベースになっている。勉強すべき理由はそれだけではなく、TypeScriptを利用することで、次の大きく3つのメリットを享受でき、安全で開発自体の生産性向上を図ることが可能になる。特にTypeScriptを採用できない理由がない場合は、TypeScriptで書くべきである。
メリット1:静的型チェックが利用可能
TSの一番大きな特徴である静的型チェック。静的型付けされたコードは常に正しいAPIドキュメントだと言える。型が付いている限り、常に正しいコードが書けるし、コンパイラでエラーを事前にチェックできる等のメリットがある。また、型があることで、エディタやIDEで入力補完の恩恵をうけることができる。
メリット2:Decoratorsが利用可能
デコレーター(@Decorators)は次世代のWeb標準(ESnext)として提案されている機能。TypeScriptでもオプションを付けることで利用可能。Angular2ではこれを推奨している。デコレーターを利用することで、コンポーネント作成にあたっての属性設定はデコレーターで、コンポーネントの実装はclassでというふうに分けて書くことができる。それによってコードの視認性も向上する。
@Component({ selector: "app-profile", template: "<p>Name: {{ name }}</p>" }) class ProfileComponent { name: string; constructor() { this.name = "laco"; } }
メリット3:Type-Base DIが利用可能
Type-Base DI(Type-Safe DI)を利用すると、DIを型ベースで行うことが可能。例えば、コンストラクタに渡す変数名が間違っていたとしても、型を指定するため、エラーを未然に防ぐことが可能。誤字(typo)に強いDIができる。DIについての詳しい説明は省略する。
import {Http} from "angular2/http";@Injectable() class MyService { constructor(private anyNameForHttp: Http) { } }
Q3. Angular1系はサポート終了になるのか?
Angular1系は、1.4系と1.5系が今後もサポートされ続ける。これがステーブルとなり、基本的には破壊的変更は入らない。もし、破壊的変更が入る場合は、1.6、1.7とバージョンが上がっていく予定で、遅れてバックポートしたものが1.5にもマージされることになる。
Angular1.5ではComponent Helperが追加された。これは、Angular2への移行をサポートするためのもので、将来的に移行を検討している場合は、使っておくと良い。また、Angular2のRouterについては、Angular1用のライブラリが出ており、利用することでAngular2とほぼ同じAPI、書き方で実装することができる。
Q4. 双方向バインディングはなくなったのか?
存在する。しかし、Angular2は原則単方向バインディングを利用することになっている。双方向バインディングを実装したい場合は、二重カッコ[()]で記載する必要が出てくる。
<input [(ngModel)]="myName">
このように記載すると実行時に、以下のように単方向バインディング+イベントハンドラが自動生成される。
<input [ngModel]="myName" (ngModelChange)="myNameChanged($event)">
Q5. Dirty checkはなくなったのか?
存在する。しかし、Angular1に比べて爆速で動作するようになった。理由は、Angular2は実行時に変更検知を行うためのコード生成を行う。具体的には、Angular2の各コンポーネントは、自分自身の変更検知のために、専用のChange Detectorという変更検知器を生成する。それぞれのコンポーネントに最適化された変更検知器のおかげで、Dirty checkのパフォーマンスが改善(10msで100000チェックが可能)された。watchの個数は基本的に気にしなくて良くなる。
Q6. サーバサイドレンダリングはできるようになるのか?
Angular Universalというnodejs上で実行されるAngular2が存在する。コアのコードはAngular2とまったく同じ。また、nodejsにかぎらず、今後は、Java/php/.net/python等の環境でも利用できるようになる予定。
Q7. WebComponentを利用しているのか?
利用していない。しかし、Angular2はWebComponentと併用可能である。例えば、ShadowDom。Angular2は独自の機能でShadowDomをエミュレート(CSSのスコーピング)を行うことが出来る。
@Component({ selector: "my-component", encapsulation: ViewEncapsulation.Native }) class MyComponent{}
ディフォルトはViewEncapsulation.Emulated
である。もしブラウザにShadowDomの機能がついていれば、 ViewEncapsulation.Native
を指定することで利用可能。パフォーマンス面では、ブラウザのShardDomを使うほうが早い。現時点ではChromeでしか動作しないが、対応ブラウザがChromeの場合や、Electron上で動作させる場合は、こちらを活用してパフォーマンス向上を狙ってほしい。
2. Angular2を構成する基礎技術について
次に、Angular2を構成する基礎技術について解説する。Angular2は様々な技術を利用して作られているので、個別の技術について理解すると、より効果的にAngular2を習得することが出来る。
SystemJS
SystemJSは動的なモジュールローダー(NodeJSのrequire
と同じような役割をもつ)である。SystemJSはES.nextのimport
、export
に対応するのが特徴で、将来ブラウザに実装されるモジュールローダーのポリフィル的存在。これを活用すると、遅延ローディングが可能になる。必要なコンポーネントのみを都度読み込む事が可能になり、よりパフォーマンスが向上する。
しかし、利用は必須ではない。JavaScriptのライブラリを静的に読み込みたい場合(npmなどでダウンロードしてくる場合)は、今までどおりBrowserifyやWebpackなどが利用可能。動的ロードしたい場合のみ、SystemJSを使えば良い。
RxJS
Angular2を利用するにあたって必須の機能。Observableのポリフィルとして利用されている。Observableはリアクティブプログラミングに基づいた考え方であり、Promise同様に非同期処理を実現する。Angular1はPromiseで、Angular2はObservableで非同期処理がそれぞれ実装されている。両者には様々な違いがあるが、Webの非同期処理についてObservableの利点を幾つか挙げる。
onkeyup等のDOM Eventに関しては、連続して発生した場合に、Promiseではその発生順序を知るすべはないが、Observableではイベントの順序どおりに処理が可能になる。DOMのAnimationについては、Promiseでは一度始まるとそれが完了するまで値は取れないが、Observableでは途中で処理をキャンセルすることが可能。WebSocketの通信についても、ストリームとして順序どおりに扱うことが可能になり、Ajaxに関しては処理途中でキャンセルが可能になる。
このように、Webにおける非同期ではObservableの方が適しているシーンが多々ある。そのため、Angular2では非同期処理の根幹はObservableで実装されている。そのため、RxJSとObservableの修得は、Angular2を学ぶためには必須とい言える。
Zone.js
ZonesというES.nextに提案されている機能のポリフィル。これを利用すると、非同期処理のコンテキストを開発者が自由に設定可能になる。具体的には、setTimeout等あらゆる非同期処理の前後にフック可能なポイントを挟むことができる。
Webにおける非同期処理の後にはかなりの確率で何らかの変更が行われる可能性がある。例えば、Ajaxでレスポンスを受け取った後はそれを受けてModelが変更されるなど。そのため、Angular2では、Zone.jsを利用し、全ての非同期処理の後に変更検知処理を行っている。処理速度も早い。
reflect-metadata
リフレクションのためのAPIを追加するためのポリフィル。reflect-metadataの機能もES.nextに提案されている。Angular2は内部的にTypeScriptのコンパイルに利用している。インストールは必要だが、開発者は覚えなくても問題はない。
3. Angular2を学ぶうえで必要なもの
次に、Angular2を学ぶ上で理解しておくことを幾つか取り上げる。
Angular2はAngular1よりシンプルになった
Angular1はAPIが多すぎたため、Angular2ではかなりシンプルになった。データバインディングと双方向バインディングの設定方法、イベントハンドラの設定方法はかなりシンプルになった。また、APIについても基本的には’@Component’を覚えれば良い。
Angular2はパフォーマンスが改善されている
Angular1はdirty-checking
、two-way bindings
、$digest loop
が遅いと言われてきたが、Angular2でChange Detection(変更検知)が革命的に変わり、パフォーマンスが改善された。
Change Detection
Change Detectionは、例えば、Modelのここが変更になったらViewに描画するなどの処理を行う際に必要になる。重要なのは、どこでどんな変更が起きたかを素早く検知して、それを反映すること。Angular2の変更検知メカニズムはよく考えられている。全てのコンポーネントには個別のChange Detecter(変更検知メカニズム)が存在する。そして、Angular2の全てのコンポーネントはツリー構造になっており、変更検知が必ず一方向(親から子へ)に行われるようになっている。そして、各コンポーネントでは変更検知を行うかどうかを個別に設定可能になっており、親のレベルで変更検知を停止したり、子のレベルで変更検知を停止したり、非常に柔軟で戦略的な変更検知の設定が可能になっている。
Angular2では静的解析ツールが利用可能
Angular1では静的解析ツールが利用できなかった。例えば、バインディングの記述に[]を利用するようになったため、機械的にバインディングかどうかのチェックが可能になっている。
まとめ
Angular2を学ぶためには、ES.next、Decorators、Observables、Zones等、最新のWeb標準技術について学ぶことが大前提である。Angular1の登場(2009年)から、Angular2の登場までの間に、Web標準の世界は大きく変わった。最新のAngular2がAngular1とまったく異なっているのは必然であり、この世界で生きていくには、勉強し続ける必要がある。枯れた技術にしがみついてはダメ。何もかも最新のものを使う必要はないが、最新の技術に常に目を向けて置く必要はある。
最後に、Angular2を使うのは素晴らしいことだが、まだベータ版であることを忘れてはならない。今後BREAKING CHANGES(破壊的変更)が発生する可能性が十分にある。そのために、チェンジログは必ず読むようにする。どうにもならなければコミットログも読む。そして、それ以上深く関わりたければ、issueを出したりPullRequestを送りましょう。それがハードルが高いと考える方は、カンファレンスに参加したり記事を書いたりしよう。開発者にTwitterで質問するのも効果的。
セッションをもっと詳しく知りたい方は?
以上で、セッションの書き起こしは終了です。
稲富駿氏のセッション資料はこちらで公開されています。
セッション動画もYoutubeで公開されているので、ぜひご覧ください!