0%

Reagent入門 - Part3: クライアントとサーバーの通信パターン

Reagentを使うとクライアント側で独立したSPAは実装できますが、サーバーとのデータ通信や、Reactのstateとpropsを抽象化してくれるratomの状態をサーバーとどうやって同期をするのかが問題です。クライアントだけで完結するアプリなら良いですが、多くのアプリはデータを永続化するためのバックエンドに何らかのデータベースが必要になります。StackOverflowに興味深い議論があったのでいくつか設計のパターンを調べました。

データベースの同期

ClojureScriptにはDataScriptというDatomicのクライアント版のようなインメモリのデータベースがあります。クライアント側にもデータベースを持つアーキテクチャには、Couchbase Sync GatewayCouchbase LiteMeteorminimongoがあります。後者2つはクライアントのデータベースの状態はにautomagicallyな仕組みでサーバーと同期されますが、DataScriptの場合は同期の仕組みを作る必要がありそうです。

とても便利そうなのですが、ちょっと複雑になりそうで手がでません。

WebSocketとAjax (REST)

ちょうどHapi.jsactionhero.jsでREST APIとWebSocketを一つのサーバーで提供する設計を試しています。どちらのプロトコルも用途にあわせて使い分けができるようにしたいです。

WebSocket、Ajax、core.asyncのすべてに対応するライブラリが増えています。

LuminusはClojureScriptを使う場合にReagentを推奨しています。Reagentからサーバへcljs-ajaxを使ってAjax通信をします。おそらく多くのSPAの実装パターンがこれに該当すると思います。

REST APIを提供するライブラリはLiberatorを採用することが多いです。

core.async

まだcore.asyncについて理解できていないのですが、ClojurScriptとClojureの間をcore.asyncで通信できるようです。

RPC

HoplonのサーバーサイドはCastraのRPCライブラリを使います。クライアント側からmkremote関数を使ってサーバー側defrpc関数を実行するようです。

Comparing ReagentにReagentとの比較があります。HoplonはClojur/ClojureScriptを使いやすく統合するためにBootを採用してビルドや開発環境が充実しています。

フルスタック

Clojure / ClojureScriptのフルスタックフレームワークを調べてみました。Reagentに対応していない場合もあります。

まとめ

Keeping Client State Up-To-Date In Reagent / Clojurescriptの議論で気にいったパターンはSPAをデータベースのクライアントの1つとみなすデザインです。

処理に必要なデータはスナップショットとして最初にクライアントに取得します。SPA側でデータを加工したあとにサーバーにsubmitします。SPAが対象のデータをリモートで処理している間の一貫性は保証されますが、処理中に他のクライアントがサーバーのデータ更新をコミットしていればsubmitに失敗して操作をやり直します。

これは昔からあるアーキテクチャでリッチクライアントと呼ばれていたFlexやGWT、ExtJSなどでよく実装していた手法です。業務系アプリだと意外とうまくいきます。同じレコードを並行して更新させないようにしたり、頻繁にデータを更新しないなど、仕様を工夫するのが現実的なようです。