bouzuya.hatenablog.com

ぼうずやのにっき

vdom-rxjs-ssr の server-side をつくった

2016-02-15 につくった bouzuya/vdom-rxjs-ssr の server-side のことを書く。

bouzuya/vdom-rxjs-ssrvirtual-dom および rxjs での server-side rendering を検証するための project 。そして bouzuya/virtual-dom-ssr の後継だ。まずは、この「 virtual-dom-ssr → vdom-rxjs-ssr への経緯」について書いておく。

virtual-dom-ssr は virtual-dom での server-side rendering を検証するための project だ。virtual-dom-ssr については過去に何度か書いている。

はじめは Cycle.js の利用を検討していたが 2016-02-03 で不適切だと判断した。代わりに virtual-dom + EventEmitter で書きはじめたのが virtual-dom-ssr だ。

virtual-dom-ssr は virtual-dom に限らず、他の部分の検証も兼ねている。たとえば path-to-regexp を使って server-side / client-side で routing を共有している。ほかにも bouzuya/promised-state という state contianer を用意している。

virtual-dom-ssr をつくる過程でいくつかの発見があった。たとえば「 EventEmitter よりも RxJS のほうが書きやすい」というのがそうだ。 2016-02-06 時点で出てきた一文はそれを踏まえている。

一日 EventEmitter でゴリゴリ書いてみた結果、 DOM driver 以外の使用を避けて、副作用も気にしなければ Cycle.js でいいんじゃないかという気がしてきた。これについてはまたそのうちに書くと思う。

Cycle.js 。ここでは cycle-core / cycle-dom のこととする。あれは virtual-dom + RxJS による実装で、いまつくろうとしているものの到達点のひとつと言っていい。同じものをつくっても仕方ないので EventEmitter を選択したのだけど、実際に書いてみると RxJS のほうがきれいに書けそうな場面が多かった……というわけだ。そういう意味で「 Cycle.js でいい」と書いた。

ちなみにここで「 DOM driver 以外の使用を避けて、副作用も気にしなければ」という制限をつけた。 その理由は Cycle.js の side-effect を driver に逃がすという方針をやめたほうがいいと考えているからだ。真面目に HTTP fetch などに適用すると、すっきりと書けるものも書けなくなるし Component を利用すると、さらにひどくなるとぼくは考えている。これはもうすこし検討が必要なのだけど……。

話を戻す。

2016-02-17 の記事にある virtual-dom-ssr の client-side routing 対応が終わり、virtual-dom-ssr にひとつの区切りをつけられたと感じた。そこで 「 EventEmitter よりも RxJS のほうが良い」や「 Cycle.js を使わない」などの条件で検証したくなった。

そして virtual-dom + EventEmitter から virtual-dom + rxjs に移行した。これが bouzuya/virtual-dom-ssr から bouzuya/vdom-rxjs-ssr への移行までの経緯だ。

続いて、今回の vdom-rxjs-ssr の server-side 実装について書いておく。

まず残念ながら server-side で RxJS に利点はほとんどないと思う。その理由は 2016-02-03 を参照すると良い。2016-02-03 では Cycle.js (virtual-dom + RxJS) を不適切だと説明している。要約すると 2 点だ。 server-side では event stream が 1 本で済むので event stream の合成が役に立たないこと。ある request に対応する response を 1:1 で返すべきところに 1:N で応答を返せる Observable の構造が邪魔になること。

そこで今回は vdom-rxjs-ssr という名前に反して RxJS を使っていない。 server-side に関しては。

  • Promise を返す initializer
  • initializer を選択するための path-to-regexp でつくられた router
  • State から virtual-dom の VTree を返す view
  • view を HTML として描画する renderToHTML

それくらいだ。あとは source code を参照してほしい。commit はこのあたりがそうだ。app/framework/ 以外は virtual-dom-ssr の残骸なので注意してほしい。app/ から見ると分かりやすいかもしれない。