Angular Ivyとは何か?

laco2net氏(以下、laco2net):よろしくお願いします。『Angular Ivy and beyond』ということで、Angular Ivyとその先について、お話しようと思います。

まず簡単に自己紹介です。laco、本名はSuguru Inatomiと申します。Kaizen Platformという会社で働いています。

フロントエンド開発をしていまして、仕事のほかにはng-japanというAngular日本ユーザー会のオーガナイザーをしていたり、Angularのコントリビューターをしていたりします。

今日お話するAngular Ivyとは何かと言うと、目下開発されているAngularの最新の機能の名前です。最近記事などでAngular Ivyという名前だけがTwitterに流れてきたりして「何だろうな?」と思っている人が多いかなと思ったので、今日はその話をしにきました。

Ivyって何だろう? 名前からまったく想像できないので、まずググってみると「蔦」って出てきます。Ivy。

もうちょっと調べるとApache Ivyが出てきて、「もうこれ何のことかわからん!」ってなるんですけど。

Angular Ivyというのは、もともとngivというコードネームで始まったプロジェクトです。IVは、「Isomorphic View engineなんじゃないか?」と言われていて誰も知らないんですけど。これを中の人に聞いたら「Maybe」って言われて、はぐらかされたんですよね。

そのIVにyを付けて、Ivyという近い単語をあてただけなので、Ivy自体に意味はないです。IとVに意味があるようです。

実態は何かと言うと、Angularの第3世代のビューエンジンです。第1世代がAngular 2.0.0が出たときの、シンプルにRendererと呼ばれていたものです。

その後次のバージョンアップ、バージョン4から現行のバージョン6にかけてはRenderer2と呼ばれるものが内部的に使われていて。今回のIvyは第3世代、この次のRenderer3になるものと言われています。

Ivyの特徴

ここからちょっと中の話になるんですが、そもそもAngularのレンダリングって何だ? というところの話をすると、AngularってテンプレートをHTMLで書くんですね。文字列の。それが最終的にDOMになるんですけれども。

その過程で何が行われるかと言うと、まずテンプレートが、文字列が一旦解析されて抽象構文木みたいなものが作られます。これはテンプレートデータと言われていて、それを実行時に変換して、実際DOMを作る関数の呼び出しに変換してDOMになるという段階を踏んでいます。

JIT compile、要するに全部ブラウザ上でやることができるんですが、それを一部ビルド時にデプロイ前にやってしまうのがAoT compileというもので。DOMを書き込む命令まで、命令的にDOMを作る関数の生成までをやってしまうのがAoT compileで、実行時にはそれを呼んでDOMを作るだけというのが現行のRender2のアーキテクチャになっています。

これはどういうことかと言うと、上が開発者が手書きするテンプレートですね。

divの中に「Hello, world!」と書いてあるんですが、これが最初の第1段階で下にviewDefとか書いてあるよくわからないコードが生成されるんです。

これが抽象的なコード、テンプレートデータと呼ばれるものです。これはとても手書きできたものじゃなくて、今完全に生成しかできないコードになるんですね。

一方Ivyはどうなるかと言うと、けっこう段階が省略されて、テンプレートHTMLからテンプレートインストラクションというものに変換され、それが直接DOMになる、DOMを吐き出すというふうに、1つ段階が飛んでいます。

これがIvyのパイプラインで、JITだと全部JITでやるので当然こうなるんですが。AoT compileだと、テンプレートインストラクションを作るところまでデプロイ前にやってしまって、実行時にはテンプレートインストラクションを実行してDOMを生成するという切り分けになります。

さっきとあまり変わらないんですが、1番変わるのは生成されるコードの性質です。上に出ているテンプレートは変わらなくて、さっきと同じdivの中に「Hello, World!」があります。

そこから生成されるコードが非常に人間にも読みやすい構造になっています。elementStartやtextのようにDOMの要素を作ったり、テキストノードを作ったりという命令にだいたい一致したインストラクションを生成するようになっていて、これがng-Ivyの特徴の大きなものです。

Ivyが生まれた3つの理由

なぜIvyを作る必要があったか? なぜRenderer2じゃダメだのか? というのは3つ理由があります。Smaller、Faster、Simplerです。

Smallerはその名の通り小さくします。何を小さくするかと言うとバンドル後のアプリケーションのサイズですね。Rendererによって今まではTree Shakingできなかった部分をTree Shakingできるようにすることで、バンドルサイズを大きく減らせると。

使っている機能だけのバンドルサイズになるというのをAngularはIvyでさらに推し進めると言うことができます。

さらに生成されるコードが、これはまあGooglerの中の人のすごいテクニックなんですけど、V8 friendlyのJavaScript codeを生成する能力に彼らは長けているので、それによって実行時に早くなると。そういったことがあります。

例えばさっきと同じdivで「Hello, World!」を出すだけだと、使う関数ってelementStartして、textを出して、elementを閉じるという。これだけのAngularの機能が必要です。

Angularにはほかにも、例えばpipeだったりいろいろありますが、これらの関数は使われていないので、バンドル時にTree Shakingで消されます。

なのでデッドコードとして消えて、実際にバンドルされるのは下の3つの関数だけになるのでバンドルサイズが削減できる。これがAngular Ivyの1つ目の恩恵です。

2つ目がFaster。Localityということで、これは理由を説明すると長くなるので省略しますけど、インクリメンタルビルドが早くなるという恩恵があります。

もう1個、Simplerは生成されるコードが読みやすくなるという恩恵ですね。デバックしやすくなる。スタックトレースの意味がわかりやすくなるみたいな恩恵があります。

Ivyは何に使われているか?

ここまではよく記事に出てるし、だいたいわかるのですが、今日はこの先の話をしようと思って来ました。Ivyが何に使われるのか?

1つはAngular Elementsです。これは何かと言うと、AngularのコンポーネントをWeb Componentsの仕様に沿ったCustom Elementsに変換するための機能です。

これが今動いてまして、Angularのアプリケーション中のコンポーネントをCustom Elementsに変換します。そのときにコンポーネントとそれに必要な最小限のAngular CoreをパッケージしてCustom Elementsにするんですね。

課題は一緒にパッケージされるAngular Coreがでかいということだったんですが、Angular Ivyによってここのサイズを小さくできることで同じサイト内にいくつもタグを貼ってもAngularのコードのサイズによって大きくならない。ネットワークを圧迫しないというのがAngular ElementsがIvyとしてやりたいことです。

もう1個、Angularの国際化対応、i18nについてです。

これは18nを生成するコードが中できれいになりましたが、とくにインフラは関係ないので飛ばします。

Ivyの可能性

僕は今日ここをとくに話しに来ました。ここから乱暴になるのでちょっと気をつけてほしいんですけど。Angularのコンポーネントをデコレータなしで書くことがIvyで可能になります。

これよくあるふつうのAngularのコンポーネントで、classがあってデコレータがあるんですけど。これをIvyがどう変換するかと言うと、デコレータを外して、中にstaticなngComponentDefというものを作ります。type、selectors、inputs、templateあたりはIvyが生成したコードですね。

テンプレートの部分だけ取り出してみました。

するとテンプレートはelementStart、text、elementEnd。下のほうは、selectorsとかほかの属性があります。

こう並べてみると、「なんかReactのコンポーネントこんなんだったなぁ」って。

考えて、考えて、考えて、考えて……。

(会場笑)

ずっと考えていると、ピコーンって閃いたんですね。「これjsxで書けるじゃん!」って。jsxToIvyという関数さえ作ってしまえば、ここの中は自由じゃんと思いつきました。

もっとやると、自分でstaticじゃなくてrenderでやって、thisをレンダリングさせてしまえば「これもうReactじゃん!」と。「やったー!」と思いました。

もっと形にすると、ngRenderとかやったらできるんじゃないか? と思ったのを、今日デモします。

これはAngularです。ngRenderというもので、Count、this.countでon-clickでcountUp。これが動いてるというところを今日見せたかったという会です。

(会場笑)

実はけっこうinitialCountとか属性を渡したり、propsを渡してたり。親のコンポーネントから子のコンポーネントを呼び出したりしてけっこう発展途上なんですけど。4時間くらいやったら書けたので、Ivyの夢は広がるぞという話ですね。

まとめです。Ivyとは何かと言うと、次世代のAngularのビューエンジンだと。裏側の話ですね。

何に注目しているかと言うと、ランタイムのサイズを小さくすることと、コンパイルを早くする、インクリメンタルビルドを早くするということと、あとAPIをシンプルにするということ。

僕が1番重要視しているのは、「可能性がでかくてメタプログラミング勢にはたまらん!」というところを今日は推していきたいということで、これでおしまいにしようと思います。ありがとうございました。

(会場拍手)