InstantClickの導入

本Weblogは今月初め(Feb,2017)デザインを一新し,新しい技術も採用した. ページ移動を高速化する技術もそのひとつ. ここではそれを実現しているJavaScriptライブラリ"InstantClick"の導入方法を紹介する. InstantClickが素晴らしいのは導入がとっても簡単なこと.

導入方法

2つのscriptタグを各ページの</body>直前に書き込むだけで導入終わり. こんな風に.
...
<script data-no-instant src="https://cdnjs.cloudflare.com/ajax/libs/instantclick/3.0.1/instantclick.min.js">
<script data-no-instant>InstantClick.init();</script>
</body>
</html>
Bloggerに導入する場合はdata-no-instantdata-no-instant='true'などに書き換えよう. この属性については後々紹介するとして,まずはInstantClickがどのように高速なページ移動を実現しているか,体感してみよう.

どのように動いているか

まずは下のリンクへ飛んで,"Click me"リンクをクリックしてみよう. http://instantclick.io/click-test "Click - Hover"の横に秒数が出る. リンク上にマウスカーソルが乗った瞬間から実際にリンクをクリックするまでの時間が表示されるのだ. 平均すると500ms(0.5秒),速くても200ms(0.2秒)かかるらしい. InstantClickはこの時間を利用してリンク先のリソースをロードする. そしてリンクのクリックを合図にtitlebodyタグの中身を入れ替える.
通常はリンクをクリックした後に必要なリソースをロードし,真っさらなページを用意して,その上にレンダリングするため時間がかかる.
InstantClickを導入するとリンクにカーソルが乗った時点でリソースのロードがはじまる. クリックと同時に今いるページのコンテンツとロードしたリソースをpjaxで差し替える(pjaxについてはページ下部参照). 通常の移動よりも一手間少ない!
ユーザーからしてみれば魔法のように一瞬でページ移動したかのように見える(実際は一部が差し替わった同じページ!). 真っさらなページから書き直す手間が省けるので,体感速度は大幅に向上する. ちなみに,スマートフォンの場合はリンクに指が触れた瞬間から指が離れた瞬間までの時間を利用するそう. ロードの時間が十分に取れない場合,もしくはロードが上手く行かなかった場合などは通常のページ移動になる.
titleとbodyタグの中身しか入れ替えないためheadタグの中身は最初のページと同じになる. もしも,各ページでheadタグ内に定義したスタイル(CSS)やスクリプトが異なる場合は,多少調整が必要.

Config(各種設定)

ページ移動する際,bodyタグの中身を差し替えるため,bodyタグの中にscriptタグがある場合,移動する度に実行される. もしも最初の一回だけ実行させたいスクリプトがある場合はscriptタグの属性にdata-no-instantを追加しよう. InstantClickはこの属性があるscriptタグを再評価の対象から外してくれる.

先読み(ロード)するタイミング

カーソルがリンクに乗ると自動でリソースをロードすることにはデメリットもある. ただカーソルがリンクの上を通過しただけでもそのリソースがロードされてしまう. このような無駄を省くためのオプションがいくつかあるので紹介.
mousedown
リンクをクリックし始めた時(マウスのボタンを押した瞬間)からマウスのボタンを離した瞬間までの間にロードさせたい場合は次のようにする. InstantClick.init('mousedown'); この設定にすることで,無駄なロードを省くことが出来るが,ロードの時間は短くなる.
delay
カーソルがリンクの上に乗ってから何秒後にロードを始めさせるかを設定することも出来る. InstantClick.init(50); 上の場合50ms(0.05秒)の遅延. おすすめは50msから100msの間だそう. 100ms以上ならば'mousedown'の方が良いかもしれないとのこと.

ブラックリスト

InstantClickでは先読み(ロード)をしないリンク(aタグ)がいくつかある.
  • targetやdownload属性のあるリンク
  • ドメインかプロトコルが異なるページへのリンク
  • 同じページのアンカー(#anchor)へのリンク
これらのリンクはクリックしても通常のページ移動になる. また,data-no-instant属性を付けることで個別にリンクをブラックリストへ追加することも出来る. <a href="アドレス" data-no-instant>リンク</a> このリンクはクリックしても通常のページ移動となる.

コールバック函数

InstantClickからのコールバックを得ることができる. これらはInstantClick.init()の前に書く.
Change
最も良く使うであろうコールバック. InstantClickによるページ移動が完了した際に呼び出される. いわゆる移動先ページのonload. DOMContentLoadedやjQuery.ready()によって実行されるコードはここへ移すことをおすすめしている. InstantClick.on('change', /*コールバック函数はココに書く*/); これを利用してGoogle Analyticsのコードを次のように書くことが出来る.
<script data-no-instant>
  (function(i,s,o,g,r,a,m){
    i['GoogleAnalyticsObject']=r;
    i[r]=i[r]||function(){(i[r].q=i[r].q||[]).push(arguments);},i[r].l=1*new Date();
    a=s.createElement(o),m=s.getElementsByTagName(o)[0],a.async=1,a.src=g;
    m.parentNode.insertBefore(a,m);
  })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
  ga('create', 'アナリティクスID', 'auto');
  // ga('send', 'pageview'); この部分をコールバック函数の中へ入れる.

  InstantClick.on('change', function () {
    ga('send', 'pageview', location.pathname + location.search);
  });

  InstantClick.init();
</script>
このコールバック函数はisInitialLoad引数を取ることが出来る. 例えば次のようにすると,最初のページでは何も起きず,ページ移動先ではアラートが表示されるようになる.
InstantClick.on('change', function (isInitialLoad) {
  if (!isInitialLoad) alert('The power of pjax!');
});
Fetch
ロードが始まった時に呼び出される. InstantClick.on('fetch', /*コールバック函数はココに書く*/);
Receive
ロードが完了した時に呼び出される. InstantClick.on('receive', /*コールバック函数はココに書く*/);
Wait
リンクがクリックされたが,先読み(ロード)が出来なかった場合に呼び出される. InstantClick.on('wait', /*コールバック函数はココに書く*/);

プログレスバー

InstantClickでページ移動するとページ上部にプログレスバーが表示される. 次のCSSでプログレスバーの色を変更することが出来る.
#instantclick-bar {
  background-color: gray;
}
プログレスバーを非表示にしたい場合は#instantclickのdisplayをnoneにする.
#instantclick {
  display: none;
}

このWeblogの設定

Bloggerテンプレートからの引用を一部だけ紹介する.
<script data-no-instant='true' src='https://cdnjs.cloudflare.com/ajax/libs/instantclick/3.0.1/instantclick.min.js' type='text/javascript'/>
<script data-no-instant='true' type='text/javascript'>
  //<![CDATA[
  /* Google Analytics Code */
  (function(i,s,o,g,r,a,m){
    i['GoogleAnalyticsObject']=r;
    i[r]=i[r]||function(){(i[r].q=i[r].q||[]).push(arguments);},i[r].l=1*new Date();
    a=s.createElement(o),m=s.getElementsByTagName(o)[0],a.async=1,a.src=g;
    m.parentNode.insertBefore(a,m);
  })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
  ga('create', 'アナリティクスID', 'auto');

  InstantClick.on('change', function (isInitialLoad) {
    ga('send', 'pageview', location.pathname + location.search);

    if (!isInitialLoad) {
      // renderKaTeX(); KaTeXについては後日紹介予定...
    }
  });

  InstantClick.init(100);
  //]]>
</script>
その他にも機能はある. 詳しくは公式サイトのドキュメンテーションを参照. http://instantclick.io/documentation

pjaxとは

ページの一部を入れ替えてページ移動したように見せる技術のこと. どういうことかピンと来ない方はWebページの歴史を少し遡ってみよう.
昔々,ひとつのページで見ることのできるコンテンツは決まっていた(静的:staticであった). 新しいコンテンツを見るためにはリンクをクリックしてページ移動する必要があった. 必要なリソースをダウンロードし,真っさらなキャンバスにロードしたコンテンツを表示していた. ある人が考えた. JavaScriptを使ってページの一部分だけを新しいコンテンツに差し替えれば一から表示し直す必要が無くなると(動的:Dynamicになった). これが後にAjaxと呼ばれる技法. ページ移動せずに新しいコンテンツを表示できるこの技法は瞬く間に話題となり,昨今のWebアプリを支える技術となった.
しかし,Ajaxは同じページの一部を差し替えるだけなのでページ移動にはならない. つまりブラウザの履歴に残らないので,ブラウザの戻るボタンで前の状態に戻すことが出来なかった. そこに新しい技術"pushState"が登場する. これはページ移動で無くともブラウザに履歴を残す機能で,戻るボタンで前の状態へ戻ることが出来る. popStateという逆の技術とペアで,これはブラウザの進むボタンでまた入れ替え後の表示を再び得られるという機能になっている. Ajaxでユーザーの目に見える部分を丸々差し替えれば,ページ移動が高速になったように見える. これがInstantClickの始まりである.
pjaxとはpushStateとAjaxのカバン語. ページの一部のみを入れ替え,ブラウザの履歴にも残す. 魔法のような技術.
4057275934500207726 http://www.storange.jp/2017/02/instantclick.html http://www.storange.jp/2017/02/instantclick.html InstantClickの導入 2017-02-17T22:06:00+09:00 http://www.storange.jp/2017/02/instantclick.html Hideyuki Tabata 200 200 72 72