fluxxorとsocket.ioを使ってチャットを作った。大変ミニマムな感じの実装を心がけてて、今後何かWebアプリを作る時はこれを少し組み替えて作るぞというのを意識してる。ようするに低機能最低限でしょぼい。サーバー側はexpressとmongodb。
https://github.com/shokai/node-flux-boilerplate
herokuでも動く
https://node-flux-boilerplate.herokuapp.com/
クライアントはこんな実装
Fluxアーキテクチャ
Reactはなんとなくわかってfluxをやるか、と思ったらflux npmの中がdispatcherしかなかった。flux.DispatcherのwaitForの実装
まずこのへんを読んでフムフムなるほど(わかったようなわからないような)となる。
Flux | Application Architecture for Building User Interfaces
で、このスライド見たらわかりやすすぎて気絶した。とりあえずなんらかのfluxフレームワーク使ってチャットでも作る事にした。
あとこっちも、フレームワークなしで最低限のfluxを自作するとしたらこんな感じになるのね、とわかって気が楽になる。
これ読んでおけば、Fluxxor等のフレームワークがどういう工夫をしているか差分を理解しやすくなりそう。
10分で実装するFlux
Fluxxorというフレームワークを使う
http://fluxxor.com/
FluxxorはFluxなフレームワークで、StoreとActionとDispatcherを担当する。ReactをViewとして使うこと前提に作られている。
この記事がとてもわかりやすい
Fluxなフレームワーク、Fluxxorの紹介 – マルシテイアは月の上
で、Fluxxor+ReactにSocket.ioを追加してチャットをつくってみて、こんな感じの実装になった。
fluxはaction→dispatcher→store→view→actionの4つの部品で構成されるが、fluxxorは三叉のロゴのとおりDispatcherが無くてaction/store/viewだけになる。
Dispatcherはfluxxorを使うことでactionとstoreに内蔵されるようになっている。そしてactionからはdispatch関数のみが、storeからはbindActionでの受信のみがアクセスできる様になっているので、action→storeの1方向にしかメッセージが流れない。試してないけどwaitForで順序制御もできるようだ。
fluxorのstoreにはeventemitterが継承されていて、emit(“change”)するとViewにイベントが飛ぶ。ViewはcreateClassした時のmixinsにFluxxor.storeWatchMixin(Store名)を指定すると、changeイベントを受けたらrenderを呼ぶようになっている。ここでも1方向のメッセージングが強制される。
Viewからactionを呼び出すのはthis.getFlux().actionsの下に関数が生えているので、それを呼び出す。
ふつうにfluxを自分で作ったら、dispatcherがどこからでも見える場所にあったりとかで、1方向にしかメッセージを流さないことを心がける事はできても、メッセージの逆流を防ぐ実装をするのはちょっと面倒臭い。fluxxorに乗ってやると円環の理が強制的に生まれる。
socket.ioどこに置くか問題
socket.ioからの入出力はactionを通してfluxとやりとりする。
受信
socket.ioからチャットメッセージ受信→action→storeのlogsに追加→reactがView更新
送信
チャット送信ボタン押す→action→socket.ioでサーバーに送信
socket.io関係のコードをどこに置くかでけっこう迷った。
最初はChatStoreに持たせようとして、でもただの「接続しました!」みたいなStore関係ないメッセージ表示するようなコードはどこに置くのか。
結局fluxの外に独立した部品として設置してactionで通信することにしたけど、送信時のactionからのdispatchを受信させる方法が良くない。dispatchはstoreのbindAction以外にも、flux.on “dispatch”, (type, payload) ->でも受信できるけど、
An action of type send-chat was dispatched, but no store handled it dispatcher.js:105
というwarningがどうしても出される。これを避けるにはどうしてもStoreのフリをするしかないし、そもそもdispatchがstoreじゃない所に飛ぶ可能性を作るのはせっかくfluxとかいう円環の理を作ってバグの場所を特定しやすくした意味がぶち壊しになるのでやめた。
おとなしくactionから関数を呼び出すことにした。socktes/という別ディレクトリを掘ってその中にsocket.io関連のコードはまとめて、fluxとのやりとりは必ずaction経由でやる。