Vueを昔触った後Reactをどっぷり触ってまたVueを触ってReactを触った感想
最近ReactとVueをどっちも触る機会があったり、「ReactとVueどう選定するの?」という問いを投げられ、スッと答えられなかったな、と後悔があったりしていたので、Vueを触って得られた感想をまとめてみる。
結論としてなにか新しいことを発見したというものではなく、世間で言われている事を自分なりに再構築しただけの結論になったと思う。
TL; DR
- Vueからは全体的にGentleさを感じる事が多く、良い点だと感じた
- 大規模になるときReactの堅牢さは魅力的。Vueが大きくなった時に支えられ設計が出来るかは個人的には懐疑的。
- 「こうだったらVue、こうだったらReact」みたいな分岐点があるというわけではないので、最終的には好みになってくると思う。ぞうさんが好きかきりんさんが好きか。
これまでのフレームワーク遍歴
今回の話をするにあたって、僕と各フレームワークの付き合いをまとめておくと、
- Vue(ver. 0.8ぐらい)を管理画面で利用(中規模程度、半年ぐらい)
- React(ver. 0.14〜15系らへん)にどっぷりはまって使う。本番環境のユーザーユースな部分で(1〜2年)
- Vue (ver. 2.5あたり) をどっぷり最近3ヶ月ぐらい触る。
- Reactでアドバイザーみたいな感じでいくつかお手伝いしたりしながら手元でもReactをいじり始める(最近はgatsbyjs)
こんな流れで、あっちこっち行ったり来たりしている。
なので比重としてはReactの方がどっぷりな側から、Vueはこんな感じでした、という視点でまとめている。
Table of Contents
今回は、Vueで良いと思った所、慣れなかった所、最後にまとめという流れで話を進めていく。
Vueの良いなと思った所・関心したところ
◎コミュニティの手厚さ
Vueで一番良い、羨ましいなと思ったのはエコシステム・コミュニティのGentleさだった。ほんとになんでも提供してくれているし手厚さがある。
メジャーなvuexもvue-routerからマイナーそうなvue-rxまでぜーんぶvuejsという公式orgのお膝元で開発されている。
これはビギナーを混乱させないし、経験者でも多くの場合助かるだろう。
また、ラインナップを見る限り、Vueチームも取り扱うライブラリも慎重に選んでいるので、「公式なのに品質が低い」みたいなことを避けているのかなと感じる。
片一方のReactでは、react-nativeやreact-vrなどのコアな所に注力する一方、reduxもreact-routerもfacebookから距離を取って開発されていて、それぞれ独立性が高く保たれている。(正確にはfluxなど公式なものの、あまり流行ってない)
ユーザーとしては「どれ使ったら良いの?」という審美眼が求められ、ハードルを上げてしまっている。
とはいえ、最近はcreate-react-appがfacebookのorganizationになっていたり、少し風向きが変わっている感じもする。このへんはVueの影響もあるのかもしれない。
◎Vuex
VueのGentleさが一番凝縮しているのはVuexだなと思った。getter
による公式なcomputed props
の提供、mutation
を許容してaction
を使う煩雑さを軽減、非同期処理を公式サポートする部分は、Reduxで辛い部分を解消していると感じる。
原理主義的なReduxから外れるのは否定できない一方、それらはどれも現実問題必要になってしまうので辛くなり、 Reduxの不評を集めてしまうポイントだ。
最近は対抗馬としてunduxなども出てきていくつかの問題を解決しようとしているが、うまくVuexが逆輸入されたらいいよなーと感じている。
◎CSSの扱い
ReactでのCSSもstyled-componentsなどによる解決やCSSModuleでの解決は安定してきたものの、CSSに愛憎のある自分からするとどうにも邪道さを感じてモヤッとしてしまうところがある。
ここに対してで言えば、VueのCSSの解決方法はいい塩梅の妥当さを感じる。<style scoped>
で記載すればある程度CSS汚染を防げるし、それで防げないカスケードも防ぎたいならちょっと記述は冗長になるが<styled modules>
も用意されている。
— — —
誤解無き様に言っておくと、ここで言及しているのはあくまでCSSというツールについてのみ。
デザイナとの協業という点にはReactもVueも有意差は無いと感じている。
Reactでもコンポーネントが適切に分解されている状況はデザイナフレンドリーになるし、Vueでもディレクティブが混在しているテンプレートをやり取りするのは事故になりやすいと感じている。
◎<slot>
による取り回し、SEOフレンドリーさ
最近はGoogleが頑張っているので昔ほどセンシティブではないものの、SEOを気にしたい場合まだjsでのみレンダリングするのは時期尚早感がある。
Vueでは下記のように <slot>
を利用する事である程度までなら自然にマシンリーダブルに記述する事が出来る。
Reactだとなかなかこうは行かない。DOMにレンダリングしたものを吸い出そうとするのはかなり邪道になってしまうし、じゃあSSRにするかというと途端にハードルやコストが上がって割に合わなくなる。
◎日本語ドキュメント
どれを見ても日本語ドキュメントがほとんど揃っているし、更新が早いと感じる。
Google翻訳が精度高くなった昨今とはいえ、やっぱり人手で翻訳された文章によって使うエネルギーが下がるのは嬉しさがある。
Vueでなじまなかった所
△Component.extendのOptionの多さと挙動
Reactの場合、ざっくり言えばstate
とprops
とrender
さえわかれば基本は良い。ライフラサイクルメソッドもあるが、普段使いはしないのでたまにググれば十分になる。
Vueの場合、少なくとも普通に作るとdata
, props
の他にmethods
, computed
はあたりは触ることになる。標準のAPIには watch
と propData
もあり、覚えるまでずっとドキュメントを開き続ける必要があった。どれが重要なのか肌感を掴むまで時間がかかったなと感じている。
今はちょっとずつ慣れてきたが、未だにそれぞれどれが関数渡してどれがObjectを渡すのかは間違えて怒られたりしている。
また、 this.someValue
で暗黙的に data
, props
, computed
が計算されるが、暗黙的なものがあんまり好きではないので、個人的に微妙かなと感じるところだった。
△テンプレートに直接記述するディレクティブ
いわゆるディレクティブと呼ばれるv-if
やv-for
が全然慣れない。
特にfor
周りは微妙にjavascriptの構文とも違う独自言語になっている感じで、スッと頭の中にマッピングされてない。
割と脳内レンダリングが得意な方なのだが、自分が書いたテンプレートでも後で読んだ時脳内レンダリングに結構時間を取られる印象がある。
functional componentを利用して1コンポーネントあたりのディレクティブ利用量を減らすことで一定の対応は出来るが、そうなるとファイル数が無駄に増えてしまうため、トータルでの可読性はあまり上がっていかずに困っている。
△双方向バインディング
一度単方向フローに慣れてた人間に、双方向バインディングは辛い。双方向バインディングが使われているVueファイルを見るだけで頭がパンクしてしまう。もうこれは一生戻れない気がしている。困った。
この機能は昔からあるものなので、後方互換の意味合いもあるんだとは思う。ただ、非推奨というわけでもないので、「Vueには双方向バインディングがある」という気持ちで向き合わなければならない。
△TypeScript, Flowとの相性
ある程度の規模以上を考えた時、やっぱりしっかりした型はほしいのだが、Vueはなかなか型にキビシーなと感じるところが多い。
vue-class-componentが公式から提供されてるものの、まだまだ不穏な空気があるデコレータを使うのは躊躇がある。かといってVue.extend({})
で記述するのもちょっと冗長で・・・という感じになってしまう。
flowはなんだかもっと辛そうな雰囲気を感じたので試していない。
TypeScriptは2.8でjsxに対応したり、TS側がReactに寄せてきている感じがあるのでこの辺りを求めると、型周りはReactのほうが楽に恩恵にたどり着ける印象がある。
— — —
TypeScriptについてもう一言言うと、型そのものの魅力もあれば、VSCodeでのIDE並の補完も強い。これを失うのが痛いという部分もある。
例えばコンポーネントを呼び出す場合、Vueの場合、標準だとhtml内、import句、componentsの呼び出しと三度呼ばないといけない。
一方 React + VSCode + TypeScript では、一度コンポーネントを記述したら一発で補完してくれるので非常に重宝する。
△生DOMへの向き合い方
ReactとVueを比べた時、生DOMへのアクセスをより自然に記述出来るのはVueだと言える。
Reactでは例えばd3のようなライブラリと組み合わせようとするとラッパーを採用するか、refsでゴニョゴニョするので不自然な記述になる。
一見Vueの方が嬉しく感じるかもしれないが、むしろこの点はReactの方が好きだ。というのも、そもそも生DOMを操作するのはテストも記述しづらく、バグの温床になりがちなので避けるに越したことはないと感じている。
この観点で考えると、Reactの方が「例外的な事を例外的に書いている」ということがわかりやすくしやすく、個人的には好ましく思う。
これに付随して、Vueの場合、周辺ライブラリも生DOMに触っていたり、jQueryやその他DOM依存なライブラリに強く依存しているものが一定数あると感じる。
そういうライブラリは後々負債になる確率は高いため、公式以外のライブラリを選定する場合はVueの方がより選定に慎重さが求められると感じた。
締め
コンポーネント設計への悩み
Reactをやっていて一番悩むポイントはReduxにまつわる非同期処理であったりデータ処理だったりと、ロジック関連が多かったように思える。
一方のVueで最も悩んだ(悩んでいる)所はその逆で、ビューやコンポーネント周りの設計や責務分割だった。
React+Reduxでは Presentational Container(表示だけするコンポーネント)と Container Component(ロジックを持つコンポーネント)を分離する、という書き方が推奨されていて、それに従ってSFCを使うなりして切り出していけばコンポーネントはコード量が膨らんでも可読性が保てたり、デザイナとの協業も容易に作れていた。
しかしVueではmethods
や computed
の他にディレクティブもあり、普通に書いているとコンポーネントがビューとロジックが混ざってしまったり、どのコンポーネントでどんな処理をすべきかと言うことの責務を切り分けるのが悩ましく感じる場面が多かった。
少数のコンポーコンポーネントであればさほど問題は顕在化しない事に思われるが、一定の数を越えた時に無視出来ない問題になりそうで、安定させるにはどうしたらいいんだろうか?というのは悩ましく感じている。
もちろんVueでもReactのようにPresentation Componentを意識して分離することは可能だが、前述のfunctional componentの記述通り、やってみるとどうもイマイチな感じで、Vueにとっては不自然なやり方なのではないか?と個人的には感じている。
それぞれの特性
初期においてはReactはライブラリ選定やセットアップにペインがあるというのはある一方、Vueの初期コストを極力下げる姿勢というのを感じることが出来た。
中期フェーズで一定の規模になった際、Vueにおいて複雑にならない設計を保つのが難しいそうだし、堅牢性を保てるんだろうか?というのは今の所疑問を持っている。
片一方Reactにおいては、一定規模以上になったとき初期に払った分の堅牢性が効いてくるのではないだろうかと感じる。
誤解を恐れずに言うと、Reactはsimple寄りで、Vueはeasy寄りというのが近いかなと感じている。
どっちを選ぶか
元々「ReactとVueどう選定するの?」と問われた所からスタートしたまとめだったが、「そそられると思う方でいいのでは?」という身も蓋もない結論しか出てこないのが今の所だなと感じている。
個人的なところで言えば、Reactの今後の進化は結構楽しみだし、Vueはまだ攻略しきってない感もある。
どちらからも学ぶ事はあるし、フロントエンドは式年遷宮を避けては通りづらい領域でもある。あまり深く悩みすぎず、フットワーク軽く開発していきたい。