sinatraとbackbonejsでpjax(pushState + Ajax)してみた

rubyの軽量フレームワークsinatraBackbonejsでpjaxをやってみたので備忘録。

HTML5からはhistoryオブジェクトにpushStateやreplaceStateメソッドが追加され、履歴のスタックを操作できるようになりました。pjaxは、そのpushStateとAjaxを利用したブラウザの戻る・進む機能が使える技術。
通常のリクエストと異なり、必要な箇所だけをAjaxで取得するためデータの転送量を削減できる。
具体例でいうと、あのGitHubで使われてるやつ。

以下は個人的なメモ。
ヘッダー情報にHTTP_X_PJAXが付与されている場合はpjaxの処理をさせる
[sourcecode language="ruby"] class Sinatra::Request def pjax? env['HTTP_X_PJAX'] || self['_pjax'] end end [/sourcecode]

これでrequest.pjaxでアクセスがpjaxか判別。ページ全体ではなく、必要なコンテンツだけを返してあげればいいので、
sinatraの場合はlayoutをfalseにしてやる。

[sourcecode language="ruby"] get '/pjax1' do erb :pjax1, :layout => !request.pjax? end [/sourcecode]

backbornjsの方は、ajaxのリクエスト前にヘッダーにX-PJAXを付与する。

[sourcecode language="javascript"] $.ajaxSetup({ beforeSend: function(xhr) { xhr.setRequestHeader('X-PJAX', true); } }); [/sourcecode]

これで、pjaxでリクエストできます。
ブラウザの戻る・進むボタンを押したときに発生するpopStateイベントを使って
コンテンツの内容をpjaxで変更してます。

[sourcecode language="javascript"] $(window).bind("popstate", function(e){ var id = location.pathname; $('#content').text(''); if('/' !== id) $('#content').load(id); }); [/sourcecode]

backbornjsはURLのhash値を監視してルーティングしてるので、pjaxの用にしないといけないのですが、URLを奇麗にしたかったので以下のように
URLを分解してます。

[sourcecode language="javascript"] $('a').bind('click', function (e) { e.preventDefault(); router.navigate($(this).attr("href").substr(1), true); }); [/sourcecode]

Comments