Turbo Drive とは何か?
はじめに
Rails 7.0 で rails new
すると、turbo-rails gemがインストールされ、app/javascript/application.js
に import "@hotwired/turbo-rails"
と記載されています。turbo-railsとは何なのか検索してみると、どうやら Hotwire について知る必要があったので、調べてみたところ、さらに Hotwire も複数の要素から構成されていることがわかりました。
この記事では Hotwire を構成する要素の一つ Turbo Drive について試してみたことをまとめました。
Hotwire
Hotwireは、JavaScriptを極力書かずにモダンなアプリケーションを作成するためのフレームワークです。開発者の好みのサーバー側プログラミング言語を使ってリッチなアプリケーションを作れるという触れ込みです。
Hotwire自体はライブラリではなく、実態は複数のライブラリを統合したものです。
詳しくは解説してくださっている記事がありますので、そちらをお読みください。
turbo-rails
TurboはHotwireの中心となる要素です。
TurboはTypeScriptで書かれたサーバー側言語に依存しないフレームワークですが、サーバー側言語との接続にはアダプタを書く必要があります。Railsで使う場合はすでに用意されていて、便利なヘルパーを使うことができます。このヘルパーを実装するのが turbo-rails gem です。
Turbo Drive
Turbo Drive は Turbo フレームワークのうち、ページナビゲーションを強化するライブラリです。以前は Turbolinks と呼ばれていたものの後継になります。
Turbo Drive を使うことで、webアプリ内の画面遷移を高速にできます。
仕組み
対象となるリンクをクリックすると、Turbo Driveはブラウザの処理を中断し、History APIを使ってブラウザのURLを変更し、fetchを使って新しいページを要求し、HTMLレスポンスをレンダリングします。
フォームも同様に、フォームの送信はフェッチリクエストに変換され、そこからTurbo DriveがリダイレクトをたどってHTMLレスポンスをレンダリングします。
レンダリング中、Turbo Driveは <body>
要素をそのまま置き換え、<head>
要素の内容をマージします。JavaScriptのウィンドウとドキュメントオブジェクト、および <html>
要素は、レンダリングの度には変更されません。
できること
- ページ遷移の高速化
- リンククリック
- フォーム送信
できないこと
- ページの部分更新
サンプル
Turbo Drive 有効
Rails 7.0 では次のimportにより、デフォルトでリンク/フォームのTurbo Driveは有効になっています。
// app/javascript/application.js
import "@hotwired/turbo-rails"
<%= link_to "Show this article", article %>
<%= form_with(model: article) do |form| %><% end %>
<a href="/articles/1">Show this article</a>
<form action="/articles/1" accept-charset="UTF-8" method="post"><input type="hidden" name="_method" value="patch" autocomplete="off" /><input type="hidden" name="authenticity_token" value="AQb9UxLWjAWELLjZB1oUWnbQs1RDqLapTHTt6XSyGTcnWF388j5502Nr4Hym1EPYHIhEz8QzF7oU3ph_SszhuQ" autocomplete="off" />
</form>
Turbo Drive をリンク/フォーム単位で無効化する
リンクやフォームに data-turbo="false"
属性を付与すると、そのリンクやフォームではTurbo Driveは無効になります。
Railsのビューヘルパーを使う場合、次のようになります。
<%= link_to "Show this book", book, data: { turbo: false } %>
<%= form_with(model: book, data: { turbo: false }) do |form| %><% end %>
<a data-turbo="false" href="/books/1">Show this book</a>
<form data-turbo="false" action="/books/1" accept-charset="UTF-8" method="post"><input type="hidden" name="_method" value="patch" autocomplete="off" /><input type="hidden" name="authenticity_token" value="YkPysdqDmax-mD3FHFYd-iHC-UgIhUjmpDyttQB8TFaqkx707_p0iVh5tPG_wDXW8HH5nHDqlhntXdycoxzJUA" autocomplete="off" />
</form>
セッション中のすべてで Turbo Drive を無効にする
Turbo.session.drive = false;
を設定すると、そのセッションでの Turbo Drive が無効になります。
import { Turbo } from "@hotwired/turbo-rails"
// サイト全体で無効にする
Turbo.session.drive = false;
↓のサンプルでは有効/無効をチェックボックスで切り換えられるようにしてみました。
イベント
Turbo Drive が有効なリンククリック時に処理を行う、Turbo Drive の fetch をキャンセルしたい、レンダリング前後や要素差し替え後に何かしたいなど、用意されたイベントを利用することができます。
まとめ
Turbo Drive を使うとサーバー側からはただのHTMLを返すだけで、高速なページナビゲーションを実現できます。
ページの一部分だけ書き換えたい場合は Turbo Frame を使います。こちらについては別記事で試してみたいと思います。
Discussion