何が言いたいのかというと、Vue.js, React, Angularなどここ最近のフロントエンド界隈を賑わせているフレームワークはたくさんあるけれども、その中でビューレイヤという責務に対して最も薄いアプローチをしているのがReactで、もっとも関数らしい副作用のないアプローチができるんではないかなと思ったということだ。僕自身、よっぽどPerformance-consiousなウェブ・アプリケーションを作るのでもない限り、フロントエンド・フレームワーク最強論議はすごくナンセンスだと思っていたけれどアーキテクチャの観点から考えるのであればフロントエンド・フレームワークの良し悪しが出てくるのは比較的意味のあるものではないかと感じる。
僕はフロントエンド・アプリケーションにおけるビューをV=Component(State)
のように考えている。この数式臭いものが表すのは、コンポーネントはステートを食ってビューを返すだけの純粋な関数だというところだ。アプリケーションにはFlux実装のようなビューレイヤ以外の責務*1が常に存在することを前提にしているが、よっぽどペライチのウェブサイトを作るでもない限り、とりわけSPAであればアプリケーションにおけるデータ管理の責務はもはやビューに置くには適さないと考えているからだ。
つまり、ステートはすべてFluxアーキテクチャの上で管理し、コンポーネントはビューを作るだけに専念させたい。ビューとは純粋な関数だ。ステートを受け取り、HTML(JSX)を返す。このアプローチができる最近のナウいフレームワークはReactなのではないかと思う。たとえば、ReactではReact.SFCというのがTypeScriptで使える。うれしい。
interface Greeter { name: string; } const GreeterComponent: React.SFC<Greeter> = ({ name }) => { return ( <div>Hello! {name}</div> ) }
React Stateless Functional Component with TypeScript
このような関数っぽいアプローチを優れた点は、まず副作用が少なく安全だったり、テストしやすいということだ。そして、コンポーネントがステートを持つことができるというReact.Component継承クラスのコンポーネント定義をやめることで、常にステートはコンポーネントと別責務として考えることができる。「ここのコンポーネントのステートは他のコンポーネントで使っていないのでローカルにします」「いやいや...」みたいな議論をするのをやめて、ステートは常に決まった場所で管理しようという方針立てにつながる。つまり、コンポーネントはステート管理の場所ではなくなり、あくまで「ステートの写像」*2でしかなくなる。
「コンポーネント・ライフサイクル・ハンドラが無いんだけど、それが絡む処理はどう書けばええねん??」という話もでてくるだろう。けれど、コンポーネント・ライフサイクルに頼るべき処理が必要になるということは、おそらくコンポーネントのなかでステート管理をしようとしている可能性が高い。コンポーネント・ライフサイクルは見方を変えればコンポーネント内にあるローカル・ステートの変更検知だ。これはコンポーネントの中でステート管理をしているということと限りなく近い。純粋な関数としてDOMのレンダリングのみにフォーカスするコンポーネントはこうしたステート管理とは切り離して考える必要がある。
さて、これをやるだけなら実際jsrenderやyo-yo、Handlbars.jsとかでええやんけ、という話もありそうだが、確かによいと思う。ただ、パフォーマンスの観点ではきっとReactのが優れているような気がしなくもない。そういう意味で、Reactに優位性があるのではないかと思う。
*1:Fluxのデータフローの責務が、果たしてビューにあるかないかはここでは話さない