なんかrails3.2でpjaxを公式にサポート云々みたいな話をきいてたけど、ふたを開けてみたらそれっぽい差分がちょっと見当たらなくてついカッとなってしまったので、既存の資産で試してみることにしました。pjaxを。
rails向けのpjax-railsというgemがありますが、半年ぐらいメンテされてなくて不安なので、pjax-railsのなかで使われてるjquery-pjaxを普通につかうことにします。jquery-pjaxも4ヶ月ぐらい動きがないみたいですが、カッとなっているのでそういう細かいことは気にしません。
https://github.com/defunkt/jquery-pjax
さっそく読み込んで、aタグにイベントをバインドしましょう。差し替える要素に"data-pjax-container"という属性が記述されてるものとします。
$("a:not([data-remote])").pjax("[data-pjax-container]")
data-remote以外も無視する必要がある場合はセレクタに追記するといいです。
これだけだとX-PJAX trueというヘッダを付けてリクエストしてるだけになるのでコントローラ側でも対応します。renderをオーバライドしてリクエストヘッダにX-PJAXがセットされていればpjax用のレイアウトにする、みたいな感じでいいんじゃないですかね。
遷移時にこじゃれたアニメーションをしたい場合は
- start.pjax
- end.pjax
あたりのイベント内で実装するといい感じにできるはずです。こじゃれるあまりにうざくならないように気をつけましょう。
$(document).bind("start.pjax", function(){});
$(document).bind("end.pjax", function(){});
aタグにイベントをつける際に$.ajaxのオプションを渡すことができます。jquey-pjaxのもってるデフォルトのタイムアウトがやや早いかなという感があるので、サイトの応答速度に応じて明示しておくのがいいでしょう。サーバが200を返していてもタイムアウトまでレスポンスがないとlocation.hrefでふつうにリダイレクト処理が行われるようになってます。
$("a:not([data-remote])").pjax("[data-pjax-container]", {
timeout:1000,
success: function(){}
});
あとブラウザで戻るの処理をしたときにもpopstateが発火するのでこっちもバインドしておきましょう。
$(window).bind("popstate", function(){});
以上でpjaxを導入することができます。簡単ですね。
で、こんな導入手順みたいな話はわりとどうでもよいので、実際にやってみて思ったことなどを書いておこうと思います。
すっごくあたりまえのことを書きますが、サイト全体にpjaxでの画面遷移を提供した場合、pjaxレスポンスのコンテナ外で書いてるjsの読み込み処理は初回しか行われません。一般的にheadの中でjsやcssを読んだりすると思いますが、多くの場合にそれらは初回のリクエストで取得したものが使いまわされます。
都度読み込まれないということは当然$.ready()などのイベントも走らないので、前述したpjax関連のイベントなどをつかいpushState/popStateが終わったタイミングでページ初期化時に行われるべき処理の実行を明示する必要があります。
さらに各URLごとにjsやcssを分割している場合は、pjaxのレスポンスにそれらも含めるように書いておかないと、pjax遷移時と通常のGETで遷移した場合に差異が出るような挙動をするでしょう。
新規にサイト作る場合は予め意識すればいいので大した話ではないですけど、既存のサイトをpjax化するみたいな作業は軽い気持ちで始めるとイバラの道になることもあるのではないかと思うのですね。まあ現在どれだけjs使ってるかによるんですが。
初回リクエストのスコープで変数を定義しておけばpjax遷移が続く限り永続化するので、websocketのコネクションを維持しておいて通知処理を行いつつ表示コンテンツを頻繁に切り替える、みたいなケースで利用されることが多くなるんじゃないかなあとか思いました。メリット反面、これまでよりもjsのライフサイクルを意識してサイト全体を構築する必要があるので、メンテナンスの敷居はちょっと上がるんじゃないかなという所感があります。
ヘッダ表示部分やメニュー以外をpjaxで差し替える、といったようなWEB黎明期におけるiframeみたいなつかいかたの場合、レスポンスの削減には劇的に寄与しないし前述のようにjs方面で気を使う必要があって、使い所としては正直なところ微妙だなーとおもっています。まあ大雑把にやってもたしかに体感はよくなるんですけど、もっと局所的な表示を書き換えるようなケースでつかうのが効果的といえるでしょう。それなら別に今までどおりのajaxでいいじゃない、っていう人と、検索エンジンがクロールできるHTMLもついでに作れて素敵やん、っていう人と、まあ人それぞれですかね。
pjaxの使われている箇所としてgithubのツリーui部分が有名ですが、あれ以上のつかいどころ今のところ浮かばないなーと思いました。了