React に対する感情とかコンポーネント管理ライブラリの選定とか
Posted:Updated:
コンポーネント管理できそうなライブラリの選定
ここでいうコンポーネントは HTML 要素をコンポーネントに見立てるような、近代 Web フロントエンドにおける狭義のコンポーネントです。大まかな条件は次の3点。
- コンポーネント中心の開発ができること
- >= IE9 をサポートすること(切っても良さそうなんだけど...)
- 既製品・スクラッチは問わないが極端なリスクは踏めない(納期がシビア)
あとは期待度や API のセンスなど、個人的な審美眼判定に依ります。
- angular/angular : 2.0 が正式リリースしたらまた会いましょう
- jashkenas/backbone : 最近のコンポーネント管理には及ばない
- Custom Elements ( Polymer ) : polyfill が >= IE10サポート
- segmentio/deku : 振る舞いは十分だったけど、>= IE10サポート
- muut/riotjs : 悪くなさそうだったけど、独自プリプロセッサが不安
- facebook/react : みんな使ってるし...
結局 React を採用
様々な葛藤はありましたが、何の面白みもない結論に落ち着いています。
- 今や React の情報は世間に溢れているので「ググれ」が使える
- 業務に耐えうる水準で信頼性が高い(っぽい)
- 対象がPCサイトなので、ファイルサイズには目を瞑れる
- DOM Component の再利用や List まわりのチューニングが優秀(っぽい)
- ECMAScript 6 サポートが順当に行われている
- React 以上に賢い実装をスクラッチする自信とアイディアがない (!)
Flux については FRP ライブラリを組み込んだものを作りましたが、FRP を全メンバーと共有する自信がなかったのでお蔵入り。GitHub にはそのうち公開します。
React の関心と技術の分離にまつわる違和感
React を採用しましたが、その独特の世界観に何の疑問も覚えていないわけではありません。一見してキモさと禁忌しか感じない JSX を肯定する次の一句。
Templates separate technologies, not concerns.
Template は ViewPresenter が提供するデータやメソッドについての知識がなければ記述できず、このような依存関係にあるものを別々にするのは関心の分離ではなく技術の分離に過ぎない。という趣で理解しています。
確かに UI ロジックとテンプレートが近いと嬉しい
Handlebars にせよ AngularJS にせよ、ある変数をループさせるためには、どの変数が Array なのかくらいは知っている必要があります。ループ中に表示の分岐が必要なら、どんなフラグを持った Object が Array の中に入っているのかも知っているはずです。
UI ロジックをもつ ViewPresenter が形ばかり分離された Template とそれ以外の処理の板挟みになって曖昧になっていくのは珍しくありません。そこで ViewPresenter と Template を同一視してまとめたもの(コンポーネント)と、UI 以外の処理に再分類すること自体には一定の納得感があります。
本当に「技術の分離」だったのだろうか
コンテンツやセマンティクスを表現する HTML と、インタラクションや機能を提供する JavaScript は、やはり本来的な関心が異なる要素です。「技術の分離」は UI コンポーネントとしての依存関係に甘んじて、HTML を JavaScript の依り代としてしか見ていないが故の極論のようにも見えます。
後述する Virtual DOM の事情を無視すれば、やはり HTML と JavaScript は分かれて存在しているべきであり、<div className="btn" onClick={foo()}> よりも<div> が守るべき本来の姿に近いと思えてなりません。JSX で HTML っぽく記述できるだけで、前者の正体は JavaScript です。
HTML には<style> と<script> がある
同じファイルの中で見通しを確保するだけであれば Riot 2.0 や vue-component-compiler、Polymer がサポートするような HTML/CSS/JavaScript 混成ファイルになっているだけで解決する問題もあるでしょう。JavaScript に HTML らしきものを書いてメリットがあるのは、関心の問題ではなく技術的な都合が本質だと考えています。
HTML/CSS/JavaScript のうちトリックなしで他の記述言語をファイル内に含められる仕様をもつのは HTML だけであり、HTML が強者であることを忘れてはなりません。
...という下書きをしていましたが、一ヶ月ぶりにみたら「職人が丁寧に書き上げた HTML」vs「JavaScript で生成された HTML」のようにも見えてしまい、結果が同じなら管理対象は「正しい HTML」でも「正しい HTML を生成できる JavaScript」でもどっちでも良いのでは・・・という気持ちもなきにしもあらず。: (
過渡期にある技術としての React
コンポーネントの効率的な管理やアトミックな処理を今すでに使える技術の範疇で表現したかったのであって、HTML や未来の標準仕様を表現したかったわけではなかったはずです。時期的にも Web Components などとの互換性があまり考慮されていなさそうなことには納得しています。
Virtual DOM によって許された怠惰
出尽くしている話ですが、DOM の更新を常にelement.innerHTML = template(data) で済ませたいのは、少なくとも Backbone.js で書いていた頃と変化していません。
この最も怠惰な方法はパフォーマンス上の理由で慎重に扱われてきました。そのため、些細な変更は DOM 操作を手書きしたり、データバインディングによる更新で補助したりしてきました。
ところが Virtual DOM のおかげで、変更規模の大小を問わずelement.innerHTML = template(data) と同じくらい怠惰な方法で DOM を更新できるようになったことは旧来 DOM 職人にとってのメリットです。
HTML テンプレートには荷が重いコンポーネントの差分更新
コンポーネント管理と DOM 要素の差分更新を行いたいとき、これまでの String を生成するだけの HTML テンプレート的なアプローチは JSX + Virtual DOM と比べると大変です。Custom Elements を使わない限り、DOM 要素をコンポーネントとして表現するのは、HTML テンプレートのパースや内部管理の実装で少なくないコストや制約を生み出しがちです。
その点 React はrender() 内の Virtual DOM 生成そのものにはあまりコストを払っていません。コンポーネントツリーを HTML テンプレートからあぶり出して抽象オブジェクトを作ったりせず、render() 内で Virtual DOM を生成するメソッドに、コンポーネントのオブジェクトを直接渡すだけという割り切り方です。
ただの JavaScript だからこそ出来る荒技とも言えますが、少なくとも AngularJS のように計算量で頑張るしかなさそうなアプローチよりは効率的です。個人的には、この事情があるからこそ「技術の分離」という言にケチを付けつつも、JSX を Virtual DOM のための必要悪として認めている節があります。
世代交代は訪れるにせよ、触れることに損はなさそう
ここ数年のエッジな JavaScript 業界では、ひとつのライブラリが最有力の座を占めている傾向が強かったように感じられますが、React もいずれは次の最有力に今の地位を譲ることになります。
多くの人が多くの時間と関心を割いて知見を飽和させた React ですから、これまでの最有力たちと同様に当分は使い続けられるでしょうし、次の新しい最有力への乗り換えを強いられない限り、触ってみること自体に損はないと考えています。
アイディアとして生きる Flux や Virtual DOM
React そのものが最有力としての役目を終えても、Angular 2 や Polymer ほか近代的なライブラリが目指している Web フロントエンドのコンポーネント化に少なくない影響を与えそうです。
特に Virtual DOM による DOM 更新の効率化や、イミュータブルなデータフローで状態管理を凝縮する Flux アーキテクチャは、しばらく界隈の開発者の思想として残っていくような気がします。
ポエムでした
ぽえー。
Author

ahomuAyumu Sato
KINTOテクノロジーズ株式会社
Related
- 2023-11-22Next.js App Router の末端にある Client Components で懐かしの C/P パターン
- 2016-07-28React v0.14.x から v15.2.x へのアップデート録
- 2015-07-31Isomorphic Architecture を実装してるときの細かいアレコレ
- 2015-06-10yahoo/fluxible による SPA + Server Rendering の概観
- 2015-05-19ES6 class で Component 書いたら react-devtools で Unknown になったので対応した
- 2014-02-18Componentによるフロントエンドのパッケージ管理
Latest
Archives
- 2025年1月エントリー数2件
- 2024年8月エントリー数1件
- 2024年7月エントリー数2件
- 2024年6月エントリー数1件
- 2024年3月エントリー数1件
- 2024年2月エントリー数2件
- 2024年1月エントリー数2件
- 2023年11月エントリー数3件
- 2023年9月エントリー数2件
- 2023年7月エントリー数1件
- 2022年1月エントリー数1件
- 2021年8月エントリー数2件
- 2021年6月エントリー数3件
- 2020年9月エントリー数1件
- 2020年7月エントリー数1件
- 2020年4月エントリー数2件
- 2020年3月エントリー数1件
- 2018年12月エントリー数1件
- 2018年9月エントリー数2件
- 2018年5月エントリー数5件
- 2018年4月エントリー数1件
- 2018年3月エントリー数1件
- 2018年2月エントリー数4件
- 2017年11月エントリー数2件
- 2017年7月エントリー数1件
- 2017年6月エントリー数4件
- 2017年5月エントリー数4件
- 2016年12月エントリー数4件
- 2016年11月エントリー数5件
- 2016年9月エントリー数5件
- 2016年8月エントリー数2件
- 2016年7月エントリー数7件
- 2016年6月エントリー数4件
- 2016年5月エントリー数5件
- 2016年3月エントリー数1件
- 2016年2月エントリー数4件
- 2016年1月エントリー数1件
- 2015年12月エントリー数4件
- 2015年10月エントリー数1件
- 2015年9月エントリー数1件
- 2015年7月エントリー数2件
- 2015年6月エントリー数8件
- 2015年5月エントリー数9件
- 2015年4月エントリー数2件
- 2015年3月エントリー数2件
- 2015年2月エントリー数9件
- 2015年1月エントリー数2件
- 2014年12月エントリー数9件
- 2014年11月エントリー数8件
- 2014年10月エントリー数7件
- 2014年9月エントリー数4件
- 2014年8月エントリー数7件
- 2014年7月エントリー数4件
- 2014年6月エントリー数6件
- 2014年5月エントリー数2件
- 2014年4月エントリー数2件
- 2014年2月エントリー数6件
- 2014年1月エントリー数6件
- 2013年12月エントリー数7件
- 2013年10月エントリー数5件
- 2013年9月エントリー数3件
- 2013年8月エントリー数2件
- 2013年7月エントリー数1件
- 2013年6月エントリー数2件
- 2013年4月エントリー数3件
- 2013年3月エントリー数2件
- 2013年2月エントリー数3件
- 2013年1月エントリー数5件
- 2012年12月エントリー数13件
- 2012年11月エントリー数7件
- 2012年10月エントリー数4件
- 2012年9月エントリー数7件
- 2012年8月エントリー数5件
- 2012年7月エントリー数7件
- 2012年6月エントリー数2件
- 2012年5月エントリー数6件
- 2012年4月エントリー数5件
- 2012年3月エントリー数18件
- 2012年2月エントリー数10件
- 2012年1月エントリー数4件
- 2011年12月エントリー数7件
- 2011年11月エントリー数4件
- 2011年10月エントリー数13件
- 2011年9月エントリー数3件
- 2011年8月エントリー数4件
- 2011年7月エントリー数10件
- 2011年6月エントリー数13件
- 2011年5月エントリー数14件
- 2011年4月エントリー数10件
- 2011年3月エントリー数12件
- 2011年2月エントリー数14件
- 2011年1月エントリー数11件
- 2010年12月エントリー数6件
- 2010年11月エントリー数19件
- 2010年10月エントリー数15件
- 2010年9月エントリー数16件
- 2010年8月エントリー数13件
- 2010年7月エントリー数7件
- 2010年6月エントリー数2件
- 2010年5月エントリー数11件
Tags
- #a-blogcmsエントリー数39件
- #AdventCalendarエントリー数13件
- #Analyticsエントリー数5件
- #Androidエントリー数8件
- #apacheエントリー数8件
- #APIエントリー数10件
- #Appエントリー数9件
- #Backboneエントリー数7件
- #CentOSエントリー数8件
- #CMSエントリー数6件
- #CoffeeScriptエントリー数5件
- #CSSエントリー数14件
- #CSS3エントリー数9件
- #CSSNiteエントリー数5件
- #ES6エントリー数5件
- #Firefoxエントリー数8件
- #Gitエントリー数6件
- #Googleエントリー数12件
- #Gruntエントリー数9件
- #HTMLエントリー数5件
- #HTML5エントリー数14件
- #HTTPエントリー数6件
- #InternetExplorerエントリー数5件
- #iOSエントリー数9件
- #iPadエントリー数11件
- #iPhoneエントリー数11件
- #JavaScriptエントリー数94件
- #jQueryエントリー数35件
- #Macエントリー数18件
- #Mobileエントリー数18件
- #nginxエントリー数6件
- #nodeJSエントリー数7件
- #npmエントリー数6件
- #phpエントリー数39件
- #PhpStormエントリー数7件
- #Polymerエントリー数8件
- #Reactエントリー数6件
- #Rubyエントリー数7件
- #Twitterエントリー数12件
- #WCANエントリー数12件
- #WEB+DB_PRESSエントリー数6件
- #WebComponentsエントリー数9件
- #Windows7エントリー数7件
- #Wordpressエントリー数6件
- #おいしいエントリー数33件
- #おしらせエントリー数5件
- #さくらのVPSエントリー数15件
- #アクセシビリティエントリー数9件
- #イベントエントリー数23件
- #パフォーマンスエントリー数20件
- #フロントエンドエントリー数5件
- #モジュールエントリー数7件
- #モブログエントリー数5件
- #レシピエントリー数11件
- #就職活動エントリー数5件
- #屋久島エントリー数8件
- #旅行エントリー数46件
- #温泉エントリー数9件
- #読書感想文エントリー数13件
- #酒エントリー数6件
- #鹿児島エントリー数5件