環境: Rails 6.1、Turbo 7.0.0-beta.5
Hotwire(Turbo)とは
Hotwireは、Railsの作者であるBasecampのDHHが昨年発表したものです。「モダンなウェブアプリケーションを、たくさんのJavaScriptなしで、JSONの代わりにHTMLを送って作るもの」だそうです。
Hotwireは次の3つからなります。
- Turbo
- Stimulus
- Strada
といっても、Stimulusは前からありますし、Stradaはまだできていないので、実際に試してみるのはもっぱらTurboということになります。Turboは、簡単に言えば今までのTurbolinksを発展させたものです。「Turbolinksがなんかすごくなったもの」です。
参考にしたサイト
Hotwireのサイトの他に:
- Hotwire: Reactive Rails with no JavaScript? — Martian Chronicles, Evil Martians’ team blog : by Vladimir Dementyev 2021-04-12
- How to use Hotwire in Rails (Example) | GoRails : by Chris Oliver 2020-12-23
- turbo-railsのソースコード : app/ の下あたり
Hotwire (Turbo)の導入
では試してみましょう。Rails 6.1でアプリケーションを作ります。
% rails new hotwire-sample
% cd hotwire-sample
Gemfileにhotwire-railsを加えます。
gem 'hotwire-rails'
Gemをインストールします。
% bundle install
次のコマンドを実行すると、RailsアプリケーションにTurboとStimulusが入ります。
% bin/rails hotwire:install
Gemfileが自動的に修正され、Turbolinksが外されてRedisが必須になります。もう一度 bundle install
を実行します。
- gem 'turbolinks', '~> 5'
+
- # gem 'redis', '~> 4.0'
+ gem 'redis', '~> 4.0'
package.jsonでは、Turbolinksの代わりにTurboが入ります。
"dependencies": {
+ "@hotwired/turbo-rails": "^7.0.0-beta.5",
"@rails/actioncable": "^6.0.0",
"@rails/activestorage": "^6.0.0",
"@rails/ujs": "^6.0.0",
"@rails/webpacker": "5.2.1",
- "turbolinks": "^5.2.0"
+ "stimulus": "^2.0.0"
},
cable.ymlが修正されています。ActionCableを使うときは開発環境でRedisが必要なようです。なお、Turboを使うにはActionCableが必須というわけではありません。この「その1」と「その2」のサンプルではActionCableもRedisも要りません。
development:
- adapter: async
+ adapter: redis
+ url: redis://localhost:6379/1
application.jsでも、Turbolinksの代わりにTurboが入り、Stimulusの初期化(import "controllers"
)が加わります。
import Rails from "@rails/ujs"
- import Turbolinks from "turbolinks"
+ import "@hotwired/turbo-rails"
import * as ActiveStorage from "@rails/activestorage"
import "channels"
Rails.start()
- Turbolinks.start()
ActiveStorage.start()
+ import "controllers"
レイアウトテンプレートでdata-turbolinks-track
をdata-turbo-track
に変える必要がありますが、ここは自動的に修正されないので手動で直します。
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbo-track': 'reload' %>
<%= javascript_pack_tag 'application', 'data-turbo-track': 'reload' %>
なお、hotwire-railsはturbo-railsとstimulus-railsをまとめたものです。Gemfileにhotwire-railsの代わりにgem 'turbo-rails'
を加えて、次のコマンドを実行しても同じです。webpacker:install:stimulus
を実行しなければ、StimulusなしでTurboだけ使えます。
% bundle install
% bin/rails turbo:install
% bin/rails webpacker:install:stimulus
作成・更新フォーム
Turboの機能を調べるために、作成・更新フォームを作ってみます。scaffoldで手抜きします。
% bin/rails g scaffold entry title:string body:text
% bin/rails db:migrate
エラー表示を試すために、バリデーションを加えます。
class Entry < ApplicationRecord
validates :title, :body, presence: true
end
http://localhost:3000/entries
から新規作成と編集画面を試すと、Turboのために何も手を加えなくても、そのまま動作します。
バリデーションエラーのときの挙動は、これまでのRailsとは変わります。POSTでブラウザーが画面遷移せずに、TurboのJavaScriptが画面を差し替えます。URLは /entries/new や /entries/:id/edit のままです。
注意しなければならないのは、Turboを使っているときにPOST(PATCH、DELETE)メソッドでリクエストを送ったら、リダイレクトするかHTTPステータスをエラーにする(300番台か400番台のステータスを返す)必要があることです。200を返すと画面が変わりません。
def create
@entry = Entry.new(entry_params)
if @entry.save
redirect_to @entry, notice: "Entry was successfully created."
else
render :new, status: :unprocessable_entity # statusが必須
end
end
POSTのときにバグによる500エラーが出たときは、TurboはRailsのいつものエラー画面を出してくれません。これはそういうものなのか、これから変わるのか分かりません。
IE対応
TurboはIE 11で動きません。Polyfillをあれこれ入れて試してみましたが、無理そうです。
ここまでの感想
- Turboは、Turbolinksよりもめっちゃ速い。
- バリデーションエラーでPOSTによる画面遷移をしないのは、たいへんありがたい。このためだけでもTurboを使いたい。
- 今年はいよいよIEを完全に切る年になるか。
続き: