Rendr入門サーバサイドで(も)動かすBackbone.js
Rendr入門: 目次
• Rendrとは?•前提となる問題意識• Rendrの仕組み
•アプリ開発・運用の実際と、使ってみた感想•Q&A
Rendrとは?
•インタラクティブなウェブサービスを作りたい。
•同時に、高速なレスポンスを実現したい。
前提
•JavaScriptを使って、クライアント側でUIなどのインタラクティブな部分を構築。
•最初のレスポンスを早めるために、サーバ側でもHTMLをレンダリング。
どうするか?
•テンプレートにERB + Mustacheを使い、サーバとクライアントで一部を共有。
•クライアント側JavaScriptのコード量が、7割くらいを占めるようになる。
Rails + Backbone.js
•サーバのRubyと、クライアントのJavaScriptを行き来するのがストレス。
•コードが重複する(バリデーションなど)。
•サーバでのレンダリングはやめたくない。
新しい課題
そこでRendr•AirBnb社が開発したNode.js向けライブラリ。
•Backbone.jsをベースに、サーバ・クライアント間で多くのコードを共有できる。
•Expressのミドルウェア。
Backbone.js
•JavaScript MVCフレームワーク。•Router、Model、Collection、Viewから構成される。
•イベントによりモデルとビューが連動。
Rendrの動作《サーバ》
•Node.js上で、Backbone.jsアプリ(ルータ、モデル、ビュー、テンプレート)を動かしてHTMLを生成。
•CSS、JavaScriptなどアセットをコンパイルして配信。
Rendrの動作《サーバ2》
•HTML生成に使ったBackbone.View と Backbone.Model(Collection)をシリアライズ。
•Backbone.Viewとデータを関連づけるIDが、HTMLに埋め込まれる。
Rendrの動作《クライアント》
•シリアライズされたデータと、HTML上のIDを元にBackbone.ViewとBackbone.Modelを生成して関連づける。
•以降は、通常のBackbone.jsアプリと同様に動く。
つまり
•スタンドアローンのBackbone.jsアプリを、Node.jsを使って配信。
•配信時に、初回のレンダリングは完了した状態になっている。
Rendrアプリの書き方
Rendrの構成
•ルータ•コントローラ•ビュー•テンプレート•データ・フェッチャー
ルータ
•URLから、実行するコントローラとアクションの組み合わせを決定する。
•サーバ側とクライアント側共通。
ルータ設定の例app/routes.js
module.exports = function(match) { match('', 'home#index'); match('repos', 'repos#index'); match('repos/:owner/:name', 'repos#show'); match('users' , 'users#index'); match('users/:login', 'users#show'); match('users_lazy/:login', 'users#show_lazy');};
コントローラ•データの取得など、アプリケーションのロジック部分。
•元のBackbone.jsには無い。•複数の「アクション」を持つ。•サーバ側とクライアント側共通。
コントローラの例app/controllers/users_controller.js
module.exports = { index: function(params, callback) { var spec = { collection: { collection: 'Users', params: params } }; this.app.fetch(spec, function(err, result) { callback(err, result); }); }}
ビュー•データ処理部分は、サーバ側とクライアント側共通。
•サーバ側で、DOMを使うことはできない。
•クライアント側では、いわゆるBackbone.Viewとして動く。
ビューapp/views/users/index.js
module.exports = BaseView.extend({ className: 'users_index_view'});
module.exports.getTemplateData = function(){ data = BaseView.prototype.getTemplateData.call(this); return data;};module.exports.id = 'users/index';
テンプレート
•標準では、Handlebarsを使用。•サーバ側とクライアント側で、同じテンプレートが共有される。
テンプレートapp/templates/users/index.hbs
<h1>Users</h1><ul>{{#each models}} <li> <a href="/users/{{login}}">{{login}}</a> </li>{{/each}}</ul>
データ・フェッチャー•サーバ・クライアント共通で使えるAPI。
•サーバ動作時は、サーバの「データレイヤー」からデータを取得。
•クライアント動作時は、Backbone.Model/Collectionのデータ取得処理が動く。
データレイヤー•データリクエストを処理する「データレイヤー」を、自前で実装する必要がある。
•ポリタスでは、Sequelize.jsを使ってMySQLベースのデータレイヤーを実装。
開発環境•Grunt•Stich•CommonJS形式で、クライアント・サーバ共にコードを共有できる。•JavaScript・CSSのマージ•Mocha
Rendrアプリ運用の実際
動作環境•サーバ•アプリ8台•マスターDB1台 + スレーブDB8台•Capistranoでデプロイ•デプロイ時にJavaScript/CSSをコンパイル
Rendrアプリのパフォーマンス
•DBアクセスがない場合 → Expressアプリと同等の性能。
•Rendrそのもののオーバーヘッドは無視できる範囲(いまのところ)。
おわりに
Rendrを選択した理由•Sails.jsなどは、クライアント⇄サーバでのコードの共有の点で、しっくり来なかった。
•元々Backbone.jsベースのコード資産があった。
•Rendrはアプリ・コードの構成がシンプルで、AirBnbによる実績も期待できた。
Rendrにして良かった事•サーバとクライアントで、「言語」を共有できるようになった。
•サーバとクライアントで、多くの「コード」を共有できるようになった。
•Backbone.jsのコードが、アセット扱いからメイン扱いになってしっくり来た。
Rendrの気になるところ
•まだ色々未開拓。•データレイヤーに共通のお作法がない。
•頻繁に内部仕様が変わる。•ドキュメント不足してる。
Q&A
•連絡先: @mshk•その他:「rendr」で検索
Top Related