pjax(pushState + Ajax)で遷移するウェブページを作る


  • Ajax 使わずにページ全体を読み込ませるのが許されるのは小学生までだよねー!
  • でも、ハッシュフラグメント(#!)を使った方法はいろいろと問題がある ので使いたくない。
  • でもでも、pushState だって非対応ブラウザじゃだめなんでしょ?
  • そこで pjax ですよ!

pjax とは

pjax というのは pushState + Ajax を意味する造語です。Ajax の方は最早 Web 関連の技術としては常識となっていますが、pushState の方はまだそれほど一般的ではないと思います。

これは HTML5 History API を構成するものの一つで、要するにブラウザの閲覧履歴を管理するものです。

こいつを利用すると Javascript を使って実際に遷移すること無しに、ブラウザの履歴に対して追加(pushState)、置換(replaceState)、取り出し(popState)などの操作を行うことが出来ます。

長々と書きましたが、結局何をやりたいかというと、

pushState 対応ブラウザ(Firefox, Chrome, Safari, IE10

  • pjax リンクをクリックするとページの一部を高速に書き換え。
  • ブラウザの履歴も書き換わるので戻る・進むボタンにも対応。
  • URL 直打ちでも目的のページに到達します。
pushState 非対応ブラウザ(IE9以下)
  • pjax リンクは普通のリンクと同じ動作。
  • 戻る・進むボタンも普通に動く。

という、いいとこ取りです。注目は IE10 がやっとこさに対応してくれたことです。

IE9 と同じように、IE10 も Windows Vista 以上の PC では標準の環境となっていくでしょう。今までみたいに IE で非対応だから……という理由で導入を躊躇することはなくなりそうです。

実例

pjax を実現する Javascript は defunkt/jquery-pjax で公開されています。これを作った簡単なアプリを書いてみました。

PushStateTest – サンプルアプリ
delphinus35/PushStateTest – github

120825-0002.png

上部に並ぶリンクをクリックすると表がフラッシュして切り替わります。このときページ全体ではなく、書き換わった部分だけをサーバーから読み込むので非常に高速です。

また、そのたびにブラウザのロケーションバーとタイトルバーも書き換わっていることがわかると思います。戻る・進むボタンを押したときも正常に遷移します。

未対応ブラウザ(IE9 以下)ではリンクをクリックしたり、戻る・進むボタンを押すたびに画面全体が書き換わります。多少描画は遅くなるものの、コレも正常に動くことがわかると思います。

実装

クライアントサイド

pjax を使う場合、HTML 部分には何も手を入れる必要はありません。Javascript でちょっと細工するだけです。

// #list => 書き換え対象の要素
$('a').pjax('#list');

尤も、これだけではページに存在する全ての <a> タグが pjax 化してしまいます。実際には class などで絞り込んだ方が良いでしょう。

今回のサンプルでは <a> タグに rel="pjax" という属性を付けて対象を限定しています。

<a rel="pjax" href="https://blog.delphinus.dev/">トップ</a>
$('[rel=pjax]').pjax('#list');

サーバーサイド

pjax によるリクエストかどうかは以下の条件で判断できます。

  • リクエストパラメータに pjax=true が付加される。
  • リクエストヘッダーに以下の 2 つが付加される。
    • X-PJAX => true
    • X-PJAX-Container => #list(コンテナに指定した要素の ID)

今回は Perl + Amon2 を利用したので以下のようなスクリプトになりました。

package Sample::Web::Dispatcher;
use Amon2::Web::Dispatcher::Lite;
use Sample::Logic::Search;

get '/:region' => sub { my ($c, $args) = @_;
    my $stash = Sample::Logic::Search->new->search($args->{region});

    if ($c->req->header('P-JAX')) {
        $c->res->render('list.tt', $stash);
    } else {
        $c->res->render('index.tt', $stash);
    }
};

1;

簡単ですね。実際のスクリプトではもう少し複雑なことやってますが。

使い道とか

すぐに思いつくのは企業の公式サイトとか EC サイトの商品紹介ページでしょうか。概要特長仕様ダウンロードサポート、……等々、タブがいろいろ並んであるアレです。

他には言語などのリファレンスサイトでもいいですね。複数のサンプルをタブで切り替えて見せるときに、各のタブに個別の URL を与えることが可能になります。

逆に、適さないのは各ページに個別にアクセスする必要のないサイト。Web アプリのように必ずトップページから入るものはあんまり意味がないですね。

もう一つ、リンクのクリックのたびに画面のほとんどが書き換わるサイトでも意味がありません。要するにこのブログみたいなのです。

ここまで書いて、せっかく勉強したのに使い道がないことに気付きましたorz うーむ。何か利用法を見つけんと……

One thought on “pjax(pushState + Ajax)で遷移するウェブページを作る

  1. Pingback: 2013.03.18 の気になる記事 | MISEKAKE Blog

コメントを残す