なぜ仮想DOMという概念が俺達の魂を震えさせるのか から一年、みなさまどのようなフロントエンドをお過ごしでしょうか。
僕はひたすら過去資産をリファクタしています。
需要の雰囲気
色んな所に書きましたが、去年僕が仮想DOM AdventCalendar をやったのは、「僕自身がproductionで使いたい」ので、「Reactまあいいよね」的な雰囲気を作って外堀埋めるのが目的でした。そして、その目的はおおよそ果たされたと言ってもいいでしょう。ご協力ありがとうございました。
僕自身はKobito for Windows でReactを使ってみて、そのノウハウを公開したり、今年前半は色々とアウトプットをしていましたが、後半はSpecificなアプリケーションドメインを記述することが多くて、あまりアウトプットする内容がなくなってました。
取り敢えずは、新規のプロダクトなら採用してもよい、という雰囲気ができたし、大規模フロントエンドの主敵たる、自由闊達なjQueryの存在感を減らすのに貢献していると思います。
とはいえまだまだ混乱があるのも事実で、ちょっと現状をまとめたいと思います。
React とはなんだったのか
効率的な差分描画を実現した「UIライブラリ」。それだけ。
Reactが革命的だったのは、そのアプローチの大胆さから、それまでのフロントエンドの設計の根幹をひっくり返すような設計が可能になった点です。
Universal と 「View」 の拡張
仮想DOMアルゴリズムは差分検出のための機構であり、その管理されるターゲットは「ツリー構造ならなんでもいい」よね、というアプローチがとられつつあります。つまりは ViewはDOMである必要が無く、NativeなりWebGLなりゲームエンジンのステージなり、なんでもいいというわけです。
- Yomguithereal/react-blessed https://github.com/Yomguithereal/react-blessed
- toxicFork/react-three-renderer https://github.com/toxicFork/react-three-renderer
- angular/react-native-renderer https://github.com/angular/react-native-renderer
そのような背景があり、React 0.14 では react と react-dom というパッケージに分割されました。Reactの仮想DOMアルゴリズムが吐き出すパッチの各環境に適応したレンダラーが実装できる、そういう話です。そのターゲットとして、AndroidとiOSをターゲットにした ReactNativeがある、というわけです。
環境に依存しない ES の仕様だけで完結した Pure な JS を Universal と呼んだりするのですが(去年まではクラサバ区別しないという意味でisomorphicと呼んだりしていました)、React本体がUniversalとなってポータビリティが上がったおかげで、JSエンジンがある環境なら、どこでも仮想DOMアプローチが適用可能になった、と言ってもいいでしょう。
とはいえ、 DOM以外のそれらはまだ、実験的なフェーズであり、どこまで使い物になるかはまだ評価できません。ReactNativeは「Learn Once であって、Write Once」 ではない、という表現をしています。
Flux 設計バトルの今
Fluxの定義は色々とややこしいのですが、乱暴に言うと 「仮想DOM の描画効率の良さに任せてアトミックに状態管理を行うアプローチ」です。
一番の特長は双方向性を排除した点。昔ながらのフロントエンドは描画効率の問題から、部分的にパッチするアプローチしかとりえませんでした。
Flux実装は毎日生まれ、腐り、既に大量にあるのですが、今現在はある程度 redux が推奨される傾向があります。(個人的には癖があり過ぎてどうかなと思う部分もありますが)
- rackt/redux https://github.com/rackt/redux
redux とは別の流れとして、 Rx 等のStreamを活かしたライブラリ群があります。有名なのは cycle.jsなど。
- Cycle.js http://cycle.js.org/
Rxの流行やFluxでObeservableの流行などもあり、ESの将来どこかにStreamが入る可能性がでてきました。
- zenparsing/es-observable https://github.com/zenparsing/es-observable
まだまだ落ち着く気配はないですが、一度reduxを触ってみるのを個人的に推奨しています。
Server Side Rendering
基本的にReactがサーバーサイドで要求されるのは需要は、「二重テンプレート問題」への対策にあると思っています。クライアントとサーバーで、同一のHTMLを生成する異なるテンプレートを開発し続けるコスト対策といえるでしょう。
node以外の環境では、v8を使ってevalしたstringを返し、クライアントで状態を引き継ぐ手法がとられることが多いように見えます。
- reactjs/react-rails https://github.com/reactjs/react-rails
サーバーがクライアントと強調してアプリケーションとして全体的な一貫性を保持したまま状態遷移を行うのは、はっきり言って現状 node 環境以外では難しいです。その手のものとしては yahoo の flux 実装である fluxible が比較的枯れているでしょう。
- yahoo/fluxible https://github.com/yahoo/fluxible
正直まだGoogleBotのJSクローリングは信用できない、という背景があり、SEOが要求される部分でサーバーサイドレンダリングを捨てるのは難しい気がしています。そこで跳ね上がる管理コストに対して採用していいかどうか判断すべきでしょう。
React以外の仮想DOM実装
Reactはサイズが大きいのが問題で、小さな実装がある、という状況は去年から変わってないです。
- dekujs/deku https://github.com/dekujs/deku
- lhorie/mithril.js https://github.com/lhorie/mithril.js
- riot/riot https://github.com/riot/riot
大きな変化としては、 Angular も Incremental DOM というアプローチを試しており、細部は異なりますが基本的には仮想DOMと似たような状態管理となります。
- https://github.com/google/incremental-dom
- Incremental DOM ざっと見たやつ https://gist.github.com/azu/8f1afa948eeb2da3ad00
結局Angularも仮想DOM的なアプローチを採用する見通しで、その結果 angular をReactNativeで使うという悪魔合体のようなモノも出てきました。
- angular/react-native-renderer https://github.com/angular/react-native-renderer
僕も仮想DOM実装を途中まで書いた奴があるんですが、思いの外難しくて途中で放置してます…。
これから先起こること
適当な予想
- サーバーレスアーキテクチャでフルスペックなサイトの実現が試される
- Custom Rendererの現実的なユースケースが発見される
- Observable表現の使い道が(再)発見される
- Flux のコントロールフローがasync/awaitフレンドリーなインターフェースになるのでは
- Web Assembly で 仮想DOM/Flux が実装され、JS以外の環境に波及する
- Google Bot がSPAのクローリング精度をあげて、SSRなくてもいいよねという雰囲気ができる
- Flux が淘汰された後、次世代のアプローチの名目で次のパラダイムが探索される
現在わかってる問題としては、あるページ内で共通の親を持たない複数のComponentが協調するのが難しく、ここで何かパラダイム的な進展があるのを期待してます。
おわり
僕が持ってる世界観だとこんな感じでしょうか。
仮想DOM/Fluxアドベントカレンダーはまだ参加者を募集してます。 http://qiita.com/advent-calendar/2015/vdom-flux
フロントエンド設計論からReactのパフォーマンスチューニングまで、是非ご参加ください。