👻

Turbo Drive とは何か?

2022/01/27に公開

はじめに

Rails 7.0 で rails new すると、turbo-rails gemがインストールされ、app/javascript/application.jsimport "@hotwired/turbo-rails" と記載されています。turbo-railsとは何なのか検索してみると、どうやら Hotwire について知る必要があったので、調べてみたところ、さらに Hotwire も複数の要素から構成されていることがわかりました。

この記事では Hotwire を構成する要素の一つ Turbo Drive について試してみたことをまとめました。

Hotwire

Hotwireは、JavaScriptを極力書かずにモダンなアプリケーションを作成するためのフレームワークです。開発者の好みのサーバー側プログラミング言語を使ってリッチなアプリケーションを作れるという触れ込みです。

Hotwire自体はライブラリではなく、実態は複数のライブラリを統合したものです。

詳しくは解説してくださっている記事がありますので、そちらをお読みください。
https://techracho.bpsinc.jp/hachi8833/2021_06_09/108495
https://logmi.jp/tech/articles/324219
https://zenn.dev/en30/articles/2e8e0c55c128e0

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> 要素は、レンダリングの度には変更されません。

https://turbo.hotwired.dev/handbook/introduction#turbo-drive%3A-navigate-within-a-persistent-process

できること

  • ページ遷移の高速化
    • リンククリック
    • フォーム送信

できないこと

  • ページの部分更新

サンプル

https://github.com/takeyuweb/rails-turbo-drive-demo

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>

https://github.com/takeyuweb/rails-turbo-drive-demo/tree/main/app/views/articles

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>

https://github.com/takeyuweb/rails-turbo-drive-demo/tree/main/app/views/books

セッション中のすべてで Turbo Drive を無効にする

Turbo.session.drive = false; を設定すると、そのセッションでの Turbo Drive が無効になります。

import { Turbo } from "@hotwired/turbo-rails"

// サイト全体で無効にする
Turbo.session.drive = false;

↓のサンプルでは有効/無効をチェックボックスで切り換えられるようにしてみました。

https://github.com/takeyuweb/rails-turbo-drive-demo/blob/main/app/javascript/application.js

イベント

Turbo Drive が有効なリンククリック時に処理を行う、Turbo Drive の fetch をキャンセルしたい、レンダリング前後や要素差し替え後に何かしたいなど、用意されたイベントを利用することができます。

詳しくは Events | Turbo Reference

まとめ

Turbo Drive を使うとサーバー側からはただのHTMLを返すだけで、高速なページナビゲーションを実現できます。

ページの一部分だけ書き換えたい場合は Turbo Frame を使います。こちらについては別記事で試してみたいと思います。

タケユー・ウェブ株式会社

Discussion