はじめに
本記事は錆びかけたRailsの知識を頑張ってアップデートするアドベントカレンダーの5日目です。
引き続き猫Rails様の猫でもわかるHotwire入門 Turbo編を読み進めています。いま、2章の真ん中くらいまで来ました。
本記事では、ここまで学習してわかったRails7の特徴とそれについての考察を備忘録的に残します。Rails6までしか知らない、Rails7をまだ触ったことが無い人に役に立つかもしれません。
わかったこと及び考察
- Rails7の目玉の1つであるTurboとはリクエストに対して非同期でHTMLをレスポンスするような機能
- Rails7を使ってアプリを作ると、初期設定ではレスポンスがbodyタグの中だけ帰ってくる
- turbo_frame_tagという新しいヘルパーメソッドにより柔軟に非同期なレンダリングができる
Rails7の目玉機能の1つであるTurboとはリクエストに対して非同期でHTMLをレスポンスする機能
Turboは、Rail7で推されている機能群の総称です。これは、サーバにリクエストが来たとき非同期でHTMLをレスポンスする機能だと理解しました。
「非同期で」とはどういうことかというと、例えば一般的なWebアプリケーションでなんらかのリンクをクリックしてページが切り替わる際、サーバは「同期的に」ページを更新します。リクエストされた内容に基づきデータを作りブラウザに返すその中に、ユーザーがリクエストしたページのHTML/CSS/JavaScriptが含まれています。ブラウザはそれらを読み取って0からページを作り直し表示します。この時ブラウザの画面は、古いページから切り替わる一瞬空白になる時間があり、ユーザーはリクエストした瞬間からブラウザの表示が終わるまで操作することができなくなります。
一方非同期の場合はページ全体が再度読み込まれることはありません。ページの一部分に必要なデータがレスポンスされるのみで、ブラウザは全てが再描画されず一部分だけ更新されます。結果的にページが切り替わる空白の時間がなく、ユーザーはリクエストした後もブラウザを操作し続けることができます。
非同期の方がページが空白になる瞬間がないので、アプリを使った時の印象が「サクサク動くな」「快適だな」となりやすいです。
Rails7を使ってアプリを作ると、初期設定ではレスポンスがbodyタグの中だけ帰ってくる
Rails7とRails6以前との大きな違いは、アプリを作成し始めた初期設定(デフォルト)でリクエストが非同期になることです。返却されたリクエストはbodyタグの中身だけが非同期で更新されます。それ以外の部分はそもそもレスポンスに含まれていないのか、ブラウザには到達してそのあと使われないのかはまだ不明です。
この機能をTurbo Driveと言います。
もしリクエストを同期にしたい場合は、アプリケーションの設定ファイルを編集してオプションを指定する必要があります。
turbo_frame_tagという新しいヘルパーメソッドにより柔軟に非同期なレンダリングができる
Turbo Driveによる非同期処理はbodyタグの中身を非同期的に更新するものです。一方、Rails7から正式追加されたturbo_frame_tag
というヘルパーメソッドを使うとこのヘルパーメソッドで囲ったHTMLの箇所のみを非同期で更新できます。
例えば以下のように利用します。
<!-- 一覧 -->
<div class="card shadow mt-3">
<div class="card-header">
<%= icon_with_text("table", "一覧") %>
</div>
<div class="card-body mx-3">
<%= turbo_frame_tag "cats-list" do %>
<div class="row py-2">
<div class="col-4 mt-auto">
<%= sort_link(@search, :name) %>
</div>
<div class="col-4 mt-auto">
<%= sort_link(@search, :age) %>
</div>
<div class="col-4 d-flex justify-content-end">
<%= link_to icon_with_text("plus-circle", "登録"),
new_cat_path,
class: "btn btn-outline-primary"
%>
</div>
</div>
<%= render @cats %>
<div class="d-flex justify-content-end mt-3">
<%= paginate @cats %>
</div>
<% end %>
</div>
</div>
turbo_frame_tag
ヘルパーで囲った内部からのリクエストは特別に扱われ、その場合ページ全体ではなく、index.html.erb
の範囲のみがレスポンスされます。そして、turbo_frame_tag
で囲った部分だけが更新されます。
これはちょうど、erbでビューを作るにあたりJavaScriptで非同期通信し、返却されたデータをもとにJavaScriptでHTML要素を作ってページの一部と置き換えるといった実装と良く似ています。
Rails7ではこのような実装もJavaScriptをほとんど書かずに実現できてしまいます。確かに、生産性の高さを謳っているだけのことはありますね。