pixiv Inc.
Tuurbolinks v2.2.0 https://github.com/rails/turbolinks
- TurbolinksはRails4.0からデフォルトで導入されたgem
- railsアプリケーションを 簡単に pjaxっぽくすることが出来る。
- ajaxとhistoryAPI(popState, pushState)を利用して画面遷移
- Turbolinksで遷移する場合は、titleとbodyとcsrfトークンを変更する
- csrfトークンは変更された場合のみ
- js, cssの読み込みを初回時に行い次回以降の読み込み処理を省略することで高速化する。
$(document).ready()
が発火しない$(window).load()
が発火しない- metaタグが更新されない
<a>
タグのリンクをクリックした時の遷移をajax化して画面遷移なしにページ遷移する。- clickイベントの挙動を変えている
- 戻るボタンなどを押した時のイベントを書き換えている
- fetchReplacement時にpushStateでキャッシュしたページをpopStateで復元する。
公式では
This includes Safari 6.0+ (but not Safari 5.1.x!), IE10, and latest Chromes and Firefoxes.
と紹介されている。
- 主な判定はhistryAPI(
pushState
,replaceState
)をブラウザがサポートしているかどうか - その他はソースを参照
- 後述するが、
page:change
の判定は別なのでTurbolinksは対応していないけどpage:change
が発火することがありえる。
- js 約330行
- ruby 約80行
- 'page:before-change'
- 'page:receive'
- 'page:change'
- 'page:update'
- 'page:load'
- 'page:restore'
- 'page:expire'
<a>
タグをクリック'page:before-change'
。'page:before-change'
を設定しているeventがfalseを返す場合、通常の画面遷移を行う。- fetchReplacement がcallされる
- pushStateで現在のページをpageCashにキャッシュ
'page:fetch'
- GETのajax request を送信
- responceが返ってくる
'page:receive'
- responceをチェック。statusが400~599でない, content-typeが正しいか, ヘッダが変わってないか
- 9が正しくなければ
document.location.href = url
で遷移 - body, title をごっそり変える
'page:change'
'page:update'
'page:load'
- fetchReplacementが成功した場合、既に前のページから読み込まれているjs, cssを読み込む必要がないのでその分高速。
- ajaxで画面遷移が行われるので
$(document).ready()
や$(window).load()
が発火しない。 - headが変化してるかのチェックは
data-turbolinks-track
が付与されたnodeが前のページと内容が同じかをチェックする - レスポンスが正しくない場合は、サーバに2度リクエストする。redirectを挟む場合は4回リクエストが飛ぶ。
- サーバーがクロスドメインへのリダイレクトを返す場合、403を返す ※ここ重要
- consoleで
Turbolinks.visit('/hoge')
と実行することでfetchReplacementを実行できる。 - リンクをクリックした時の視覚的レスポンスがないため、ユーザーには不親切。
page:fetch
,page:recieve
間で視覚的にローディングしている事を伝えた方がユーザーフレンドリー。
- 初めてそのサイトに訪れた時
- ページをリロードした時
- ignoreClickの条件に一致する時
- submit時はそもそも
<a>
タグではないので動作しない - その場合、従来の画面遷移が行われる。
Turbolinksが動作しないリンク
- crossOriginLink
- anchoredLink
- nonHtmlLink
- noTurbolink
- targetLink
- nonStandardClick
-
crossOriginLink
- location.protocolとlocation.hostが現在のページと異なるページへのリンク
- サブドメインが異なる場合、fetchReplacementは動作しない
-
nonHtmlLink
- htmlで無いリンク
- 画像などへのリンクの場合、fetchReplacementは動作しない
-
noTurbolink
- 唯一明示的に開発者が設定できる
- リンクから親を逆上って
data-no-turbolink
存在するリンクは、fetchReplacementは動作しない
-
nonStandardClick
shift
,command
,alt
,control
キーなどが押されている場合は、動作しない- 別ウィンドを開く時など
- pageCashに目的のページがある場合、popStateで復元する
- 1で復元出来ない場合、
document.location.href = url
'page:change'
'page:update'
'page:restore'
- ブラウザのキャッシュから復元するので高速
- ブラウザの更新がないため、readyなどが発火しない
- キャッシュに該当のページがない場合はブラウザによりサーバーにアクセスする。
- デフォルトでは10ページ分キャッシュする
- consoleで
Turbolinks.pageCached();
を実行することでキャッシュするページ数を取得出来る。
- jQueryが提供
- どんなブラウザでも発火
- DOMが構成された後に発火
- fetchReplacementが完了した時に発火
- fetchHistoryが完了に発火
- どんな場合でもページを表示した後に発火
$(document).ready()
相当DOMContentLoaded
リスナーに追加されている- 発火タイミングは
DOMContentLoaded
+fetchReplacement
+fetchHistory
- しかし、
DOMContentLoaded
はIE6,7など古いブラウザでは実装されていないので古いブラウザでも動作させたい処理を書くときは使用しない事。
landing, reload | fetchReplacement | fetchHistory | |
---|---|---|---|
ready | ○ | × | × |
page:load | × | ○ | × |
page:restore | × | × | ○ |
page:change | ○ | ○ | ○ |
- fetchReplacement失敗時は再度レンダリングされ, landingの状態になる。
これはjqueryが提供する'ready'
とTurbolinksが提供する'page:load'
の両方で定義すること。
- 非Turbolinks遷移時は
'ready'
で発火。 - Turbolinks遷移時は
'page:load'
で発火の両方をカバーするという意味。 - Turbolinksをサポートしていないブラウザでも
'ready'
が発火するので安心。
'ready'
triggerにpage:load
を追加してくれる機能を提供。
page:change
はTurbolinksのサポート判定とは異なり、document.addEventListener
とdocument.createEvent
がブラウザでサポートされている事。- なのでTurbolinksは動かないけど
page:change
は発火する事がありえる。 page:change
は動くブラウザとそうでないブラウザがあるので注意が必要。- 特にGoogleAnalyticsは
page:change
を使うと古いブラウザのデータが取れない。
<body>
タグ内にeventを設定する処理(clickなど)をjsで書くとTurbolinksで遷移する度に設定され、何度も呼ばれる。- どうしても書きたい時は
<script>
にdata-turbolinks-eval="false"
と書けば1度しか実行されない
- 読み込む必要があるjsやcssなどが読み込まれないことを防ぐため
- 無駄なリクエストを未然に防ぐ
- cssやjsが変わるとTurbolinksで遷移できず、再描画されるのでせっかくの旨味が減る。
- 無駄にリクエストが2度飛ぶのでTurbolinks使わない場合より遅くなることも。
- サブドメインが異なるとTurbolinksはそもそも動作しないため、サブドメインごとにファイルを分けるのはあり。
- 1人で作っている
- javascriptを全く使わない
- subdomainをアプリケーションで多様している
- ページごとにcss, jsを分けて記述している
- jsを多用している
- フロントエンドエンジニアやデザイナーと共同で構築している
- Turbolinksを使うと速いっぽい (turbolinks_test)
- 戻るボタンで画面遷移する場合、キャッシュから復元しサーバーにアクセスしないため超高速。
- うまく使いこなす事が出来ればリクエスト数を減らす事が出来る。
- Rails4.0がリリースされて約1年ちょっと。そろそろ情報を調べる事ができるようになってきた。
- ソースコード読むとそんなに難しくない
- jsやブラウザの前提を覆す。
- readyが呼ばれない
- headerが変化しない等
- 割を食らうのはフロントエンドエンジニアとデザイナー
- jsをTurbolinks依存したコードを書く必要がある
- Turboliksで遷移出来ない場合、不要なアクセスが増える
- 本来Turbolinksで遷移出来るはずのリンク(ignoreClickでない)がcss, jsが異なる理由で失敗する場合,2回リクエストが飛ぶので逆に遅くなる。
- Turbolinksでうまく遷移できるように構築しているとリクエストが減りユーザーへのレスポンスも早くなる。
- 逆にTurbolinksでうまく遷移できるように構築していないと逆に遅くなる場合がある。
- 'page:change'は古いブラウザでは動かないので使用するのには注意する。
- jsを書く場合はTurbolinksの挙動を理解しておく必要がある。