TECHNOLOGY 2013.12.24

pushState + Ajax = pjax

  • HTML5/CSS3
  • Markup

マークアップ・エンジニアのトメです。
html5で実装されたhistroy操作のAPIに「pushState」という機能があります。
固有スキルは「ブラウザの履歴を操作することができる。ただしIE9以下は除外される」です。

実はこの機能、ある技術と組み合わせて発動させることによってその力を最大限に発揮することができるのです。

その唯一無二のパートナーは「ajax」。

ajaxは言わずと知れた非同期通信を利用した対話的操作が可能なWebアプリケーション構築技術の総称。
つまりはページを移動しなくてもブラウザの後ろ側でデータを取ってきて、そのデータを元に表示が切り替わって何かすごい、みたいなやつですね。

ですが、そんなajaxにも大きな弱点があります。
それは「ページ遷移が行われない為ブラウザの履歴が残せない(URLがそのまま)」ということ。

「pushState」はそんな「ajax」の弱点を補うことができる画期的な新機能。
そして、その2つを組み合わせた技術こそが「pjax」なのです!

pushStateの設定方法すごく簡単。

window.history.pushState(null,null,(ここに設定したいURL));

だけです。(他にもパラメータがあるけどココでは省略)

最低限、URLさえあればajaxを扱うことができるので実装はこんな感じ。

$('html a.pjax').on('click',function(){
    var _url = $(this).attr('href');
    getContents(_url);
    window.history.pushState(null,null,_url);
    return false;
});

function getContents(_url){
    $.ajax({
        url: _url,
        dataType: 'html',
        success: function(data){
            $('#Main').html($(data).find('#Main').html());
        }
    });
}

いろいろと省略してますが、class[pjax]が設定されたa要素がクリックされると、hrefからリンク先のURLを取得。
pushStateでブラウザの履歴を書き換え、ajaxでリンク先のHTMをパーツとして取得し、#Mainのソースの中身だけをそっくり更新、という流れです。

これだけじゃまだ未完成で、ブラウザの戻る・進む機能をつかった場合は画面更新が行われません。
そこで登場するのが履歴の移動を検知する「popstate」イベントです。

それを踏まえるとこうなります。

$('html a.pjax').on('click',function(){
    var _url = $(this).attr('href');
    getContents(_url);
    window.history.pushState(null,null,_url);
    return false;
});

$(window).on('popstate', function() {
    var _url = window.location.href;
    getContents(_url);
});

function getContents(_url){
    $.ajax({
        url: _url,
        dataType: 'html',
        success: function(data){
            $('#Main').html($(data).find('#Main').html());
        }
    });
}

popstateで履歴の移動のイベントを受け取り、「window.location.href」で取得したURLをajaxに渡す流れになってます。
実際にデータの元となるページを用意するので、pjaxでURLが切り替わった状態でリロードされてもデータの元ページが表示される仕組みになっており、ajaxと違ってSEO対策的にも有効ですね。

以上、Pjaxの簡単な説明でした。

今までPjaxを扱ってみた経験を踏まえるとサイト毎にPjaxに求める効果が異なるケースが多い印象です。

よりリッチな表現を求めて。
サーバーやブラウザの負荷軽減を求めて。
理想とするUIを求めて。

お客様の目的をヒアリングし、そのサイトに最適なPjaxが実装できればいいですね。
(もちろん、サポートブラウザ以外の対策も...)