はじめての「pjax」


こんにちは。ラクスルのWebシステムの開発・運用を行っている吉岡です。
今回はラクスルの価格表ページでも使われている「pjax」についてお話します。

pjaxとは

pjaxとは、pushStateとAjaxの技術を組み合わせたjQeuryのプラグインのことを指します。
そもそもpushStateとか、Ajaxって何ぞや?という方にそれぞれを簡単に説明します。

■ pushState
pushStateとは、HTML5で導入されたHistoryAPIの機能を使い、
ブラウザの履歴情報をページ遷移せずに変更するメソッドのことです。

■ Ajax
Ajaxは「Asynchronous JavaScript + XML」の略で (はじめて知った…)、
非同期通信でサーバーからデータをやりとりする技術です。
Google Mapsで使われて一躍有名になりました。

■ pjax
pjaxとは、これらの技術を合わせたもので、
簡単に言うと非同期通信をしつつURLを更新するものです。
有名どころだと、GitHubが導入していますね。

導入の背景

他の印刷通販の多くは価格表を取得するまでのページ遷移が多く、
紙種や納期の変更などをするにも、複数のページを行ったり来たりしなくてはいけません。

ラクスルの場合はリリース当初から価格表ページでAjaxを使用していて、
ページ遷移をせずに商品の内容を変更できるのが特徴です。
1ページで仕様の選択を完結できるので、比較的ストレスなく商品を選ぶことができます。

もともとAjaxを使っていたということもあり、導入のハードルはそれほど高くなく、
サイトリニューアルのタイミングで「pjax使おう!」という声が上がり、

  • コンテンツごとにURLが発行されるからSEO的にもいいよね
  • ブラウザバックできるからいいよね
  • URLで直接商品仕様を指定できたらいいよね
  • 新しい技術いいよね
  • GitHubが使ってるからいいよね

などなどもあり、その場のノリで導入が決まりました。

注意点など

pjaxのプラグインは2種類存在します。

defunkt版と呼ばれるものと、falsandtru版と呼ばれるものの2種類です。
違いについてはこちらにある比較表に載っています。

比較表を見ると、falsandtru版の方が機能が多く、はじめはこちらを導入しようと思いました。
ただ、うまく動作しなかったのと、いろいろ機能あるけど使わないよねー、
という結論にいたりdefunkt版での実装を決めました。

ひとつ注意して欲しいのが、falsandtru版がjQueryのv1.4.2以上から動作するのに対し、
defunkt版はv1.8.0以上から動作するという点です。
ラクスルは当時jQueryのv.1.7.2を使っていたので少し調整が必要でした。(後ほど記述)

また、pushStateをサポートするブラウザのみ有効なので、
対応していないブラウザに対してなんらかの対策(Ajaxのみにするとか)が必要です。
pushStateに対応するブラウザはこちらよりご確認ください。

いざ実装

まずはjQueryとpjaxのJavaScriptファイルを読み込みます。

<script src="/js/jquery-1.8.0.min.js"></script>
<script src="/js/jquery.pjax.js"></script>

 

pjaxには何通りか記述方法があるみたいですが、
ラクスルでは以下のように実装しています。

$.pjax({
  url:       'http://raksul.com/flyer/a4/matte/',
  container: '#change-content',
  fragment:  '#pjax-content'
});

少し説明すると、
・url: コンテンツ取得先のURL
・container: 更新するコンテンツのidもしくはclass
・fragment: 更新されるコンテンツのidもしくはclass
となっています。

例えば、セレクトボックスから紙の種類を変更したときに、pjaxの処理を走らせたいときは、

$('.paper-selectbox').change(function() {
  var url = 'http://raksul.com/flyer/a4/' + $(this).val() + '/';
  $.pjax({
    url:       url,
    container: '#change-content',
    fragment:  '#pjax-content'
  });
});

こんな感じに書けます。
簡単に説明すると、http://raksul.com/flyer/a4/ のページで紙種のセレクトボックスを変更すると、
#change-content の中身が http://raksul.com/flyer/a4/matte/ の #pjax-content の中身と入れ替わります。
それと同時にページのURLが http://raksul.com/flyer/a4/matte/ にかわります。
このとき、ヘッダーやサイドメニューの部分は一切変わらず、
指定したコンテンツ内だけが入れ替わります。

イメージとしては以下のような感じです。
クリックして拡大
pjax_img_03

 

他にラクスルの価格表で行っている設定は

・自動スクロールさせない

$.pjax.defaults.scrollTo = false;

 

・タイムアウト時間の設定(指定された時間を超えると通常のページ遷移になる)

$.pjax({
  url:       'http://raksul.com/flyer/a4/matte/',
  container: '#change-content',
  fragment:  '#pjax-content',
  timeout:   3000
});

 

pjaxの特定のイベント時に何か処理を走らせることもできます。
例えば、pjaxでコンテンツの入れ替えが終わったあとに何らかの処理をさせたいときは、

$(document).on('pjax:end', function() {
  //ここに処理を書く
});

というように書けます。
その他のイベントに関してはこちらを参照ください。

参考
https://github.com/defunkt/jquery-pjax
https://github.com/falsandtru/jquery.pjax.js