25
22

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

静的サイトをturbolinksで高速化したのでTipsを紹介する

Posted at

もともとRuby on Railsの一部だったturbolinksですが、Rails5からはturbolinksは独立し、Rails以外のプロジェクトでも使えるようになりました。そこで、静的サイトでも使ってみることにしました。かなり体感速度が上がったので、オススメです。

turbolinksとは?

turbolinksとは、ページの移動をすることなく、body内のデータの入れ替えと、head内のデータのマージを行うことで、表示を高速化するライブラリです。
ページの移動をしないため、新たにJSファイルやCSSファイルのダウンロードやキャッシュの確認もすることがなく、かなり速く感じます。

turbolinksのメリット

  • 表示が速い
  • ページがキャッシュされるので一度表示したページは高速に表示される

turbolinksのデメリット

  • jQueryのライブラリで動かないものがある可能性がある($(document).readyでのみ評価するものとか)
  • 戻るボタンで戻ったら動かなくなるものが(略
  • window, documentオブジェクトは変更されないので、そこを意識する必要がある

とはいえ、対処できないものはあんまりないと思います。

インストール

npm

turbolinksはnpmで提供されているので、導入も簡単です。

$ npm install turbolinks --save

es2015とかで使う場合はrequireしておく必要があります。

const Turbolinks = require("turbolinks");
Turbolinks.start();

jQueryユーザーのためのturbolinks入門

イベントリスナー

$(document).readyイベント

turbolinksを使うと、画面は1度しかロードされないので、$(document).readyが一度しか実行されません。
そのため、ページを移動するとそれまで存在しなかったDOMに対してのイベント類が設定されません。

turbolinksは独自にイベントリスナーがあるので、それを使います。
$(document).readyの代わりに、document.addEventListener('turbolinks:load', function(event){});を使います。

jQueryのみの場合
$(document).ready(function() {
    $(".foo").on('click', function(event) {
        console.log("clicked!");
    });
});
turbolinks版
document.addEventListener('turbolinks:load', function(event) {
    $(".foo").on('click', function(e) {
        console.log("clicked!");
    });
});

$(window).loadイベント

windowオブジェクトも変更されないので、このイベントも1度しか実行されません。
よって、なるべく使わないように変更したほうがいいでしょう。

turbolinksのイベント一覧

loadだけでなく、turbolinksには多くのイベントがあります。
それをうまく使えば、デメリットに書いていた部分はほぼほぼ解消できると思います。

イベント名 説明
turbolinks:click リンクをクリックしたときのタイミングで実行される
turbolinks:before-visit リンク先に移動する前に実行される
turbolinks:visit リンク先に移動しようとしたらすぐ実行される
turbolinks:request-start ページを取得するためのネットワーク通信を始めるときに実行される。ヘッダにデータを追加する必要があるときなどはここで処理する。戻るボタンだと発火しない(キャッシュしている場合)
turbolinks:request-end ネットワーク通信が終了したら実行される。通信エラーなどはここで処理する。戻るボタンだと発火しない(キャッシュしている場合)
turbolinks:before-cache ページがキャッシュされる前に実行される。キャッシュされるとDOMは残るけれどイベントが解除されてしまうので、不要なDOMの削除とかはここでしておく
turbolinks:before-render ページがレンダリングされる前に実行される
turbolinks:render ページがレンダリングされたら実行される。2度呼ばれることがある。キャッシュ表示で1度目。実際にデータを取得して2度目
turbolinks:load ページが表示されたタイミングで1度目が実行される。あとは移動するたびに実行される。戻るボタンで遷移しても実行される

静的なサイトの場合は

  • turbolinks:load
  • turbolinks:before-cache

くらいしか使いませんでした。

JS, CSSの置き場はheadタグ内に

CSSはともかくとして、JSファイルの読み込みはbodyタグを閉じる直前に書くのが一般的になってます。
これは、htmlのレンダリングをJSのダウンロードよりも先に行わせるためのテクニックですが、turbolinksを使う際にはこれではいけません。

turbolinksを使わない場合
<body>
  ...
  <script src="/assets/application.js"></script>
</body>

turbolinksを使う場合、bodyタグ内にJSファイルを置くと、毎回ダウンロード・実行されてしまい、高速化どころか遅くなりますし、挙動がおかしくなります。
head内に移動させましょう。

turbolinksを使う場合
<head>
  <script src="/assets/application.js"></script>
</head>
<body>
  ...
</body>

windowオブジェクトへのイベント定義について

turbolinksを使うと、window, documentオブジェクトは変更されません。
そのため、これらのオブジェクトに対してturbolinks:loadのタイミングでイベント設定をしていたら、ページを移動するたびにイベントを設定してしまうことになります。

jQueryだけの頃
// 基本的に1度しか実行されなかったのでこれでもよかった
$(document).ready(function(){
    $(window).scroll(function(e) {
        // スクロールしたら何かやる
        console.log("scroll");
    });
});
ダメな例
// ページ遷移する度にwindowに対してイベントが設定されるので絶対にダメ
document.addEventListener('turbolinks:load', function(event) {
    $(window).scroll(function(e) {
        // スクロールしたら何かやる
        console.log("scroll");
    });
});

これはそもそも、$(document).readyのタイミングで定義する必要のないものなので、イベントリスナーの中で定義するのをやめましょう。

正解
$(window).scroll(function(e) {
    // スクロールしたら何かやる
    console.log("scroll");
});

document.addEventListener('turbolinks:load', function(event) {
    // 他の処理
});

$(document).on も同様

実は$(document).onの定義も、$(document).readyの中でする必要はありませんでした。なので、これらも外に出します。

// 動的に追加する要素に対してのイベント設定はturbolinks:loadで設定しない
$(document).on('click', '.item', function(event) {
    console.log("item clicked!")
});

document.addEventListener('turbolinks:load', function(event) {
    $(".foo").on('click', function(event) {
        // turbolinks:loadで設定するのは静的な要素に対してのみ
        console.log("foo clicked!");
    });
});

まとめ

静的なサイトに関していえば、これくらいで十分でした。
また何かTipsがあったら追加していきます。

25
22
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
25
22

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?