Turbo Driveは、Rails 7から標準搭載されたHotwireの一部で、JavaScriptをほとんど書かずにSPAのような高速でスムーズなページ遷移を実現します。
この記事では、Turbo Driveの基本的な仕組みやページ遷移の種類、履歴管理、カスタマイズ方法などを初心者向けにわかりやすく解説します。
Turbo Driveとは?
Turbo Driveは、リンククリックやTurbo.visit(location)
の呼び出しでページ遷移を開始し、HTML全体を再読み込みせずに差分のみを取得してページを更新します。
キャッシュがあれば即座にプレビュー表示されるため、体感速度が大幅に向上します。
ページ遷移の種類と履歴管理
Turbo Driveでは、以下のようなページ遷移の種類があります。
Advance(進む)遷移(デフォルト)
ブラウザ履歴に新しいエントリーを追加する標準的な遷移方法です。
Railsでは通常のリンクで実現します。
<%= link_to "記事一覧へ", articles_path %>
Replace(置き換え)遷移
履歴を追加せず、現在の履歴エントリーを置き換えます。data-turbo-action="replace"
を指定します。
<%= link_to "編集", edit_article_path(@article), data: { turbo_action: "replace" } %>
またはJavaScriptで指定します。
Turbo.visit("/edit", { action: "replace" })
履歴操作による復元遷移(Restoration Visits)
ブラウザの戻る・進むボタンで自動的に発生します。
キャッシュがあればそれを表示し、スクロール位置も復元されます。この遷移は手動で指定できません。
ページ遷移のキャンセル方法
遷移開始前にturbo:before-visit
イベントを捕捉し、event.preventDefault()
でキャンセルできます。
document.addEventListener("turbo:before-visit", (event) => {
if (event.detail.url.includes("restricted")) {
event.preventDefault()
}
})
カスタムレンダリングの実装方法
turbo:before-render
イベントでレンダリング処理をカスタマイズできます。
例えば、Idiomorphを使ったDOMマージが可能です。
import { Idiomorph } from "idiomorph"
document.addEventListener("turbo:before-render", (event) => {
event.detail.render = (currentElement, newElement) => {
Idiomorph.morph(currentElement, newElement)
}
})
レンダリングやリクエストの一時停止と再開
アニメーションや認証トークンの取得など、レンダリングやリクエスト前に準備が必要な場合、一時停止と再開が可能です。
レンダリングの一時停止と再開
document.addEventListener("turbo:before-render", async (event) => {
event.preventDefault()
await animateOut()
event.detail.resume()
})
リクエストの一時停止と再開
document.addEventListener("turbo:before-fetch-request", async (event) => {
event.preventDefault()
const token = await getSessionToken()
event.detail.fetchOptions.headers["Authorization"] = `Bearer ${token}`
event.detail.resume()
})
HTTPメソッドを指定したリンクの作成
リンククリックでGET以外のHTTPメソッドを指定する場合、data-turbo-method
を使います。
<%= link_to "記事を削除", article_path(@article), data: { turbo_method: :delete } %>
アクセシビリティを考慮すると、フォームやボタンを使う方が望ましいです。
確認ダイアログ付きリンクの作成
リンククリック時に確認ダイアログを表示するには、data-turbo-confirm
を指定します。
<%= link_to "記事を削除", article_path(@article), data: { turbo_method: :delete, turbo_confirm: "本当に削除しますか?" } %>
Turbo Driveを無効化する方法
特定のリンクやフォームでTurbo Driveを無効化するには、data-turbo="false"
を指定します。
<%= link_to "通常遷移", root_path, data: { turbo: false } %>
<%= form_with url: messages_path, data: { turbo: false } do |form| %>
<!-- フォーム内容 -->
<% end %>
View Transition APIを使ったページ遷移アニメーション
ブラウザがView Transition APIをサポートしている場合、以下のメタタグを追加するとアニメーションが有効になります。
<meta name="view-transition" content="same-origin" />
プログレスバーの表示とカスタマイズ
Turbo DriveはデフォルトでCSSベースのプログレスバーを表示します。
スタイルをカスタマイズするにはCSSを追加します。
.turbo-progress-bar {
height: 5px;
background-color: green;
}
アセット変更時のページリロード
CSSやJavaScriptが変更された場合に完全リロードを行うには、アセットにdata-turbo-track="reload"
を指定します。
<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
<%= javascript_include_tag "application", "data-turbo-track": "reload" %>
特定ページで常に完全リロードを行う方法
特定ページで常に完全リロードを行うには、以下のメタタグを追加します。
<meta name="turbo-visit-control" content="reload">
Turbo Driveの動作範囲を限定する方法
Turbo Driveの動作を特定のパス以下に限定するには、以下のメタタグを追加します。
<meta name="turbo-root" content="/app">
フォーム送信時の挙動とイベント
フォーム送信時にはturbo:submit-start
やturbo:submit-end
などのイベントが発生します。
フォーム送信後はHTTP 303リダイレクトを返すことで、ページ遷移をスムーズに行います。
Turbo Streamsを使ったフォーム送信後の部分更新
フォーム送信後に複数箇所を部分更新するには、サーバーからTurbo Streams形式でレスポンスを返します。
respond_to do |format|
format.turbo_stream
end
リンクのプリフェッチとプリロード
リンクをホバー時にプリフェッチする機能はデフォルトで有効です。
無効化するには以下のメタタグを追加します。
<meta name="turbo-prefetch" content="false">
特定リンクを事前にキャッシュにプリロードするには、data-turbo-preload
を指定します。
<%= link_to "重要ページ", important_path, data: { turbo_preload: true } %>
Turbo Driveを活用して、Railsアプリケーションのページ遷移を高速化し、ユーザー体験を向上させましょう。