特集企画「アプリケーションアーキテクチャ最前線」では、さまざまな視点からアプリケーションアーキテクチャをエキスパートたちに語っていただきます。今回は、今話題のAngularJSなどのJavaScript MVCフレームワークの台頭と進化、そして新しいアーキテクチャであるFluxとそのフレームワークであるReactなどについて、既に先行して学んでいるエキスパートたちにその知見を聞いてみました。
今回はフレームワーク対決ということで、エキスパートたちがAngularとReactという陣営に分かれ、それぞれのフレームワークについて疑問点をぶつけたり、議論したりする仮想パネルディスカッションという形式でお伝えします。単なるパネルディスカッションとは違って、キーワードは「プロレス」です。まさかりの投げ合い、disり合いOKという形で、NGワードは「適材適所」「ケースバイケース」などです。白熱した議論をお楽しみください!
選手入場(自己紹介)
白石:さて、それではプロレスを始めていきましょうか(笑)。まずは、皆さんの簡単なプロフィールと一押しのフレームワークなどを教えてください。
(React陣営)
(Angular陣営)
お互いのフレームワークへの疑問点など
白石:このパネルディスカッションの今後の流れとしては、僕のほうからは何かコントロールするということはないので、レフェリーみたいなものだと思ってください(笑)。自由にやっていただければと思います。それでは、今回の本題ということで、お互いのフレームワークについて疑問点だったり、disったりということをお願いします。
小林:Angularは、1.04ぐらいのときに使っていて、実際にプロダクトに使ったんですが、結構情報がなくて辛かった思い出があります。DirectiveってよくわからないのでシンプルにControllerとかScopeとかで頑張ってやったという印象がありますね。
金井:当時は、結構そうかも。ただ今は、ドキュメントも充実してきているので今はさほど辛くはないかなと思いますね。Reactはルーティングとかバインディングとかその辺はどこまでできるんですか?
増井:React自体はほんとにViewだけなので、まったくそこはケアしないですね。Fluxは考え方なので、実はすごい小さいんですよ。Dispatcherだけなので数百行ぐらいしかない。あとそこにどうやってルーティングをやるかというのは、React Routerとか外部のコンポーネントを組み合わせて使うので、標準では持っていないです。そこは大きく違いところだと思います。
僕はAngular使っていないんですが、会社(トレタ)のほうでは、PC向けの機能は全部Angularで作ってるんです。でもそこの中の人に聞くと、CRUDみたいなよくあるアプリケーションは結構楽にできて、Angularがなかったら短期間では作れなかったと思うと言われました。ただ、そういうパターンからはずれてしまうとすごい書きにくいかもしれなくて、拡張していくとき、パターンが複雑化してきたときに本当に耐えうるのかが不安と聞きました。そういう傾向ってどうなんですかね?
久保田:何もかもScopeとかで管理しようとすると結構はまりどころ多いなというイメージがありますね。細かいインタラクションとか、例えばドラッグ&ドロップを直接使いたいときって、結局DOMを触るしかなくて、DOM触るにはDirectiveっていうものが用意されています。Directiveは、ある程度DOMに対してのいろんな機能を追加するとか、細かいDOMの操作を担当するものなんですよ。全部Controllerで管理しようとするとすごいぐちゃぐちゃになったりするんですけど、ちゃんと自分でDirectiveを作って管理すると扱いやすいと思います。
増井:なるほど。あと、Angular1系と2系ってはたから見てると、2系が年末だか来年だかに出て、結構互換性がないっていう話で、1系は捨てちゃうっていうことを聞いてそこはちょっと怖いかなっていう印象はありますね。
金井:2系が主流になって、1系が減ってこない限りはサポートするという話ですね。なので、そこは早いうちにアップデートしないといけないかもしれません。
増井:でもアップデートってまるまる書き直しなんですよね?
久保田:ng-japanでもアナウンスされてましたが、Angular2とAngular1を共存する方法はあって、1系のコードと2系のコードを混在させることができるようですね。
今からフレームワークを採用するとしたらどちらを使う?
増井:今から新しくプロジェクト始めるときにどのフレームワークで作ろうかみたいなときに、実際に作る人は悩むんですかね。
白石:実際、今作ろうと思っているものがあるんですが、悩みますね。
金井:なんでそこはAngularじゃないんですか(笑)。
白石:Angularはでかくて複雑すぎて怖いんですよね。しかもAngular2が迫っているという。この今のタイミングで採用するのはちょっと怖い。
増井:そういう意味では、僕はReact.jsがなくなっても、React.jsと同じものを書ける自信があるんですよ。FluxとReact.jsをまるっとFacebookがやめました、明日からReactはありませんと言われたときに、僕はReact全体をメンテナンスできる。まるっと同じものを作れっていわれたら、まあ頑張って作れる。Angularは作れる気がしない。
金井:作れる気はしないですね(笑)。
増井:僕は結構そこが怖くて。なので、大きいフレームワークは採用しにくいっていう面があります。あと、MVCの上にMVCを乗っけるというのは、その考え方はすごくToo Muchかなと。サーバーサイドは、サーバーサイドでMVCを作っていて、さらにクライアントサイドでMVCを作るわけじゃないですか。MVCの2階建てはアーキテクチャとして本当にいいのかっていうのはすごく思っていますね。
そもそもモデルをデータベースから作って、ちゃんとAPIにしているはずなのに、それをさらにもう一回モデルとして扱う、あんまり効率的じゃないんじゃないかっていう。Reactだけに限ると、MVCのVしかないので、そもそも書いて読んだJSONをそのままViewで表示するってことをやったりするんです。だけど、実はAPIが揃ってると結構なWebアプリケーションで、そもそもモデルまでおこさなくてもいいんじゃないかっていう気がするんですよ。
金井:JSONをとってきて出すっていうのはAngularでもできるので、それはアプリの設計によるのかなという気がしています。Angularの場合は、さらにそこから変更もできるという利点があります。
増井:それにしてはToo Muchすぎるんじゃないかと。
金井:それだけしたい場合には確かにそうですね。
増井:結構なケースがそれで済むんじゃないかっていう気はしていて。実はクライアント側でMVCが必要なほど複雑な処理するケースってそんなに多いのかなと。
久保田:まあでも実際には、もちろんアプリの要件によると思います。ハイブリッドアプリって結局JSでなんでもやるので、API叩けばそれで終わりというわけじゃなくて、むしろJSのほうでいろんなことを書かなきゃいけないって感じになるので、API叩けばそれで終わりっていう感じにはならないですよね。
APIってネットワーク越しにやるんでそれってすごく重たいし、あんまりやりたくないっていうのはモバイルアプリだと多いです。そもそもモバイルアプリだとネットワーク繋がらないってこともあるので、それを解決するにはローカルのほうでデータを保持して、繋がったら同期をとるっていう感じになるので、モデルがないとちょっと辛いという感じになりますね。
JSXは気持ち悪い?
白石:JSXがキモいんですけど…。
増井:あれは気持ち悪いんですよ実際(笑)。キモいっていうのはまったく異論ないんですけど、あれはあれで理にかなっていると思っています。DOM操作がなんで難しいかっていうとそもそもこのDOMをみたときに、これがいつどこで書き換わるかわからないし、さらにこのボタンを押したときにどこで何が起こるかわからない、イベントは1個じゃなくて100個でも張れるので。っていうのに対してJSXの場合はそういうのを一応ビューとロジックを同じところに書くことで、さらにイベントリスナーを1対1にすることによって、そういう複雑性を省きましょうという考え方なので、気持ち悪いことは認めつつ、理にはかなっているかなと。
1番の問題は、HTMLしか書けない人がこれを触れないっていう。コーダーと分離ができないっていう点ですよね。ただこれはもっと根本的な問題で、Reactは画面の一部をコンポーネントとしてスコープを作りましょうっていう考え方で、HTMLを切ってるんじゃなくて、プログラミングスコープを切ってるんですよ。それって見た目のデザインとはちょっと違って、アーキテクチャのデザインの話なので、見た目とロジックを切り離すっていうところに、そもそも無理があるじゃないかっていうことですね。
金井:そこらへん(画面の一部をコンポーネントとしてスコープを作る)は、Angularも目指すところは同じかもしれないですね。
増井:そのやり方が違うってだけなんでしょうね。
久保田:ちょっといいですか。別にJSXって気持ち悪くなくないですか。
小林:私も全然違和感ない(笑)。
白石:人によるんだ。
増井:僕も去年からReactを知ってたのに触ってなかったのは、JSXです(笑)。あれで毛嫌いして触らなくて、でもあんまり話題になってるので去年の年末年始から本格的に触ってみたというのがあります。あれは僕個人も気持ち悪いです(笑)。
小林:ぱっと見たときに、あれ(JSX)がやりたいフレームワークなのかなと思っちゃうんですよね。
増井:日本でのReactの評価は、Virtual DOMっていう技術キーワードとJSXという見た目にすごく左右されている印象がありますね。
Virtual DOMって本当に早いんですか?
白石:Virtual DOMって本当にそんなに早かったりするんですか。ぱっと考えると差分をComputeとする計算処理も必要だし、フロントのDOMと仮想DOMって2つ持っているメモリも喰いそうだなと思うんですけど、実際はどうなんですか?
小林:実際は何が一番早いかっていうのはやっぱりDOMを直接触るのが一番早いっていうのは間違いなくて、でもそれってコードとしても複雑になるじゃないですか。モデルのデータの変更された部分だけをどういう風に反映するのかっていうところが煩雑になる。Virtual DOMだと、ひとつの状態をもっておいて、パっと更新すると差分だけを綺麗に反映してくれるので、DOMを直接触るよりは遅いですが、該当部分のDOMを全部入れ替えるよりは早いという感じです。最速ではない。
白石:最速ではないと。わりとプログラマーがいい加減な処理をしてもいいってことですね。
増井:Reactはとりあえずざっくり書けば、そこそこ速いっていうような考えですね。
久保田:最近、Atomで内部でReact使ってたけどパフォーマンスのために削除したっていう話がありましたね。
白石:え、そうなんですか。もう使わなくなっちゃったんだ。
小林:最初のやつがちゃんと構造化されていなくて遅かったのをReactにして、ちょっと速くなって。そこをベースにDOM職人が頑張ってやったらさらに早くなったっていう感じですね。
Angularは謎のルールが多い
白石:Angularを触ったり調べたりしたときに僕的には謎のルールがすごい多くてとっつきにくかった。例えば、$変数が多すぎ。何々のときは$なんとかが多くて、なんだこれはっていう(笑)。
金井:あれ何なんでしょうね。$$とかあるしね(笑)。
白石:Dependency Injectionを実装したのはいいんだけど、まず引数の名前で当てるからminifyしないでねとか、minifyしてもいいように別の書き方も発明したよとか配列で指定できるようになったりとか。なんかもう歴史上の問題かもしれないんですけど、謎ルールが多すぎる感があるんですけど。そこらへんはどうなんでしょう?
久保田:やっぱりそこは気持ち悪いなと思います。でも昔からずっと実務上の必要からそういうのが増えてきたのかなと思いますね。あとから来た方がどうしたもの洗練されたものになっていくので…。
増井:Angularっていつできたんでしたっけ?
金井:結構前で、2009年ですね。
増井:そんなに前なんだ!
金井:Angular1が2012年ぐらいなので、そこで注目された感じですね。2009年にできたフレームワークが5年くらい経って実用になりつつも、辛くなってきたということでAngular2を開発しているということだと思います。Angularのいいところっていうのは、その時々で結構先のことを見据えてやろうとしていて、1系だとWeb Componentsを実装したくてDirective作ったりしてるし、Object.observe()欲しいよねっていって2way bindingを実装してみたりとか。どんどん攻めてるんですよね。
増井:そういうイメージはありますね。
実はReactは大きい
白石:ちなみにフレームワークの大きさでいうとどうなんでしょう。
増井:ReactってViewのライブラリだけのくせにすごいでかいんですよ。へたしたらjQueryよりでかい。
金井:フレームワークのサイズが大きいと、モバイルのユースケースで叩かれませんか、重いとか。Angularは相当叩かれた覚えがあります(笑)。
増井:とはいっても画像ひとつ分ぐらいですからね。Reactも実際よくあるReactのダメなところに「でかい」っていうのはいろいろ言われていて、でも現実ユーザーからそういう話があがってるわけではなく、数字で見てっていう部分があります。あと、Reactはサーバーサイドレンダリングを持っているので、ファーストビューはサーバーサイドで出しちゃって、その後にJS読み込むっていうことができるので、そういう意味では十分早いですね。面倒くさいですけど、やろうと思えばできます。
白石:今、ダウンロードしてみたんですけど、Angularがminify時で126KBで、Reactが121KBという結果に。
増井:しかも、AngularはMVCで、ReactはVだけで、ですからね(笑)。
金井:やれること全然違う。(Angularは)ルーティングからバインディングからすべてできるのに(笑)。
検索可能にするサーバーサイドレンダリング
増井:Reactのひとついいところは、サーバーサイド生成ができるのでぐぐったときに引っかかるんですよね。クローラーは基本的にはJSを実行しないので、みんなテンプレートにはじめから引っかかりそうなキーワードを入れたりとかして頑張るんですけど。でもReactはサーバーサイド(Node.js)でReactエンジンを実行してHTMLを生成することができるんですよ。そうすると例えば、基本的な部分をファーストビューで表示すると、JSが実行されなくてもHTMLで画面が見えて、JSが実行されると残りの部分が表示されるという段階的にできるですよ。
そうすれば、検索エンジンに引っかかるし、JSがもし(ブラウザで)動作しなくても本文はちゃんと読めるというメリットがあります。といってもそれをやるには、それなりに考えて書かなきゃならなきゃいけなかったり、その実行エンジンをいろいろセットアップしなきゃいけないので、手放しでできるっていうわけでもないんですが。
小林:海外はやっぱりReact導入してるところは、サーバーサイドレンダリングもやっているところが多いですね。海外のほうがサーバーにNode.jsを使うのは結構一般的で、日本だとあんまりないから意外なんですけど。サーバーサイドレンダリングできるからReact採用してるっていうとこも結構ありますね。BBCとか。
増井:ぐぐれるっていうのはでかいですからね。
白石:なるほど。じゃあAngularのほうは、どうですか?
久保田:まあAngular2に期待ですね。Angular2のレンダリングのアーキテクチャについて設計文書が公開されていて、その中でVirtual DOMを使いますと言っています。
小林:Ember.jsも次のバージョンでHTMLbarsとsimple-domを組み合わせてサーバーサイドレンダリングできるようになる予定で、これからのフレームワークはサーバーサイドレンダリングはついてきそうな気がしますね。
久保田:あと、ちょっと面白いと思ったのがサーバーサイドレンダリングだけでなく、Viewの処理をWeb Workerでやりたいっていう点ですね。
増井:Web WorkerはReactでもやるっていってますね。そんなに進んでないですが。
白石:確かに仮想DOMは、本物のDOMじゃないからWorkerでいじれるし、間のメッセージングにコストがかからなければ割と早そうですね。
増井:そこ(Reactの仮想DOM)の差分の計算までWorkerでやってしまうので、それなりの速度がでるはずですね。ChromeもServiceWorkerとか機能を強化してるのでたぶんそういうのに合わせてるんだろうなと思います。
開発速度・生産性の比較
小林:たぶんReact使っても開発速度って上がらない。書く量も結構増えますね。
増井:むしろ下がります(笑)。プログラムでひとつ大事なところは、1年後に触れるかどうかだと思っていて、よくプログラムは書くより読む時間、回数のほうが多いので読むことを考えて書くべきだって言う考えがありますよね。時間がかかっても読みやすく書いて、それによってコード量が増えるのはプログラムとしてしょうがないんじゃないかっていう考えがあって、Reactはそういう考えに近いですね。なので記述量は減らないし、同じの書いたら5〜10倍ぐらいになっちゃっていう話もあって、あきらかにめんどくさいです。
金井:AngularJSは、預ける部分が大きいので、勝手にやってくれる。コード量は圧倒的に減りますね。なのでCRUD系作るときはすごく早いです。
おわりに
このように議論はすごく白熱して、興味深いトピックスが目白押しでした。楽しんでいただけましたでしょうか。今回は「議論は平行線だった」ということで終わりたいと思います。