Turboはリンククリックやフォーム送信時にページ全体を再読み込みせず、必要な部分だけを更新することで高速な体験を提供します。
しかし、この仕組みによりJavaScriptの扱い方やキャッシュ戦略に注意が必要になります。この記事では、Turboアプリケーションを構築する際のポイントを詳しく解説します。
Turbo導入時のJavaScriptの注意点
Turboを使うと、ブラウザ内でアプリケーションが長期間動作し続けるため、ページ遷移ごとにJavaScript環境がリセットされません。
そのため、以下の点に注意が必要です。
- ページ遷移時に
window
やdocument
オブジェクトの状態が保持される - メモリに残ったオブジェクトはそのまま残り続ける
これらを意識して、Turboに依存しすぎない設計を心がけましょう。
<script>
要素の扱い方
Turbo Driveはページ遷移時に以下のように<script>
要素を扱います。
- 初回ページロード時
ページ内のすべての<script>
要素を読み込み・実行します。 - ページ遷移時(head内)
新しいページの<head>
にある、現在のページに存在しない<script>
要素を追加で読み込み・実行します。 - ページ遷移時(body内)
新しいページの<body>
内の<script>
要素は毎回実行されます。ページ固有の初期化処理に利用できます。
実行を防ぎたい場合は、data-turbo-eval="false"
を指定します。
<script data-turbo-eval="false">...</script>
JavaScriptバンドルの読み込み方法
アプリケーションのJavaScriptバンドルは必ず<head>
内で読み込みましょう。
そうしないと、ページ遷移ごとに再読み込みされてしまいます。
<head>
<script src="/application-abc123.js" defer></script>
</head>
また、バンドルの内容が変わったらURLを変更(フィンガープリント)し、data-turbo-track
属性を使って強制的にページを再読み込みさせることも検討しましょう。
Turbo Driveのキャッシュ戦略を理解する
Turbo Driveは最近訪れたページをキャッシュします。これにより、以下のメリットがあります。
- 履歴ナビゲーション時にネットワークアクセスなしでページを表示(Restoration Visits)
- 通常ナビゲーション時にキャッシュをプレビュー表示しつつ、裏で最新ページを取得(Application Visits)
キャッシュ時にはイベントリスナーや関連データは破棄されます。
キャッシュ前のページ準備(turbo:before-cache)
ページがキャッシュされる前に、フォームのリセットやUIの折りたたみなどを行う場合は、turbo:before-cache
イベントを利用します。
document.addEventListener("turbo:before-cache", function() {
// キャッシュ前の準備処理
})
また、フラッシュメッセージなど一時的な要素はdata-turbo-temporary
属性を付けることで自動的に削除されます。
<div class="flash" data-turbo-temporary>
更新しました!
</div>
プレビュー表示の検知方法
キャッシュからのプレビュー表示時には、<html>
要素にdata-turbo-preview
属性が付与されます。
if (document.documentElement.hasAttribute("data-turbo-preview")) {
// プレビュー表示中の処理
}
キャッシュの無効化方法
ページごとにキャッシュを無効化するには、<meta name="turbo-cache-control">
を使います。
- プレビュー表示を無効化(履歴ナビゲーション時のみキャッシュ利用)
<meta name="turbo-cache-control" content="no-preview">
- 完全にキャッシュを無効化
<meta name="turbo-cache-control" content="no-cache">
JavaScriptからも制御可能です。
Turbo.cache.exemptPageFromCache() // no-cache
Turbo.cache.exemptPageFromPreview() // no-preview
Turbo.cache.resetCacheControl() // リセット
JavaScriptの初期化処理(turbo:loadイベント)
TurboではDOMContentLoaded
やwindow.onload
は初回のみ発火します。
ページ遷移ごとに初期化処理を行うには、turbo:load
イベントを使います。
document.addEventListener("turbo:load", function() {
// ページ遷移ごとの初期化処理
})
イベントリスナーはイベント委譲を使ってdocumentやwindowに一度だけ登録するのが推奨です。
Stimulusを使ったJavaScriptの管理
Stimulusを使えば、Turbo DriveやTurbo Frames、Turbo Streamsなど、あらゆるDOM更新に対応したJavaScriptの初期化処理を簡単に管理できます。
<div data-controller="hello">
<input data-hello-target="name" type="text">
<button data-action="click->hello#greet">挨拶する</button>
</div>
// hello_controller.js
import { Controller } from "@hotwired/stimulus"
export default class extends Controller {
greet() {
console.log(`こんにちは、${this.name}!`)
}
get name() {
return this.targets.find("name").value
}
}
クライアントサイド変換の冪等性(Idempotent)
クライアントサイドでHTMLを変換する場合、複数回実行されても結果が変わらないように冪等性を持たせましょう。
例えば、処理済み要素にデータ属性を付与して再処理を防ぐなどの工夫が必要です。
永続的要素(Permanent Elements)の活用
ページ遷移後も状態を維持したい要素にはdata-turbo-permanent
属性を付与します。
<div id="cart-counter" data-turbo-permanent>1個の商品</div>
これにより、ページ遷移後も要素の状態やイベントリスナーが維持されます。
まとめ
Turboを使ったアプリケーション構築では、JavaScriptの扱いやキャッシュ戦略に注意が必要です。
この記事で紹介したポイントを押さえて、快適で高速なTurboアプリケーションを構築しましょう。