Rails 7のHotwireを簡単に理解する

GMOアドマーケティングの吉岡です。 今回の記事ではRails 7で追加されたHotwireという技術について、何が良いのか?どんなことができるのか?を話したいと思います。  

Hotwireとは?

大量のJavaScriptを使わずに、モダンなWebアプリケーションを作るためのアプローチ
  • JSONではなくHTMLベース
  • サーバーサイドでHTMLを生成し、WebSocketでWebブラウザへ送信
  • 構成する主な要素
    • Turbo
    • Stimulus

Hotwireを使うと何が良いのか?

  • Rails6以前の環境
    • 最新バージョンのjs(ES6)を使いたい
      • →主要なブラウザが対応していないため、ブラウザで動作するES5にトランスパイルする必要がある
  • そのために必要なパッケージとその役割
    • node.js
      • ES6のjsをサーバー側で解釈するために必要
      • ES6のjsをES5にトランスパイルするため、node.jsにbabelをインストール
      • node.jsにwebpackをインストール
    • webpacker
      • webpackを使うためのRuby Gem
      • webpackはES6で使うモジュールをまとめてトランスパイルするために必要
    • yarn
      • node.jsで使うパッケージやES6のモジュールをインストール
Rails 6ではES6のjsを使うために上記のようなパッケージを使う必要がありました。 作りはじめはいいのですが、管理するパッケージが増えたり、node.jsのバージョンが上がってくると依存関係で悩まされることが多くなってきます。
  • 外部環境の変化
    • 主要なブラウザがES6に対応
      • ES6のトランスパイルが不要に
    • HTTP/2の普及
      • 小さなファイルを非同期で送信可能
      • Webpackでのファイル結合が不要に
    • Importmaps
      • JSモジュールの論理的参照
上記のような外部環境の変化もあり、Rails6以前で使われていたモダンJSを動作させるための環境が不要となってきました。  

どんなことができるのか?

Rails7のデフォルト設定ではnode.js、yarnをインストールする必要がありません。Rails6から移行する場合は基本的にはアンインストールすることになると思います。 yarnで使っていたパッケージはどうするのでしょうか?
こちらはimportmapsで対応します。
セレクトボックスにカレンダーを追加し、日時を選択できるflatpickrをimportmapsとStimulusを使い適用してみます。
flatpickr – github.com

importmaps

importmapのインストール パッケージの追加 パッケージの削除 pinコマンドで追加するとimportmap.rbにパッケージ情報が追加されます。   config/importmap.rb 登録したパッケージはStimulusで使えます。

Stimulus

Stimulusのインストール app/javascript/controllers/flatpickr_controller.js index.html.haml

セレクトボックスにflatpickrを適用することができました。日本語化する場合はjaファイルもimportする必要があります。 上記ではdata-controller=”flatpickr”と指定していますが、これでapp/javascript/controllersにあるflatpickr_controller.jsが呼び出されます。

Turbo

次にHotwireを構成するもう一つの要素、Turboについて簡単に紹介します。
  • Turbo Drive
    • ページ遷移するときにBody内をjsで置き換える、かつてのTurbo Link。読み込みが早くなる。
  • Turbo Frame
    • <turbo-frame>というタグを使い、Turbo Driveでできなかったページの一部を置き換えることが可能。
  • Turbo Stream
    • <turbo-stream action=”replace” target=”messages”>タグを使うことで、サーバーからの更新を受け取ることができる。
    • <turbo-stream-from>タグでブロードキャスト更新を受け取り、複数ブラウザの同時更新ができる。
オンラインゲームによくある待機室とプレーヤーの関係をTurbo Streamを使って実装してみます。 

roomインスタンスに更新があったときに対象チャンネルに通知

app/models/room.rb

 

showページを表示することで対象のroomチャンネルを購読

show.html.haml _room.html.haml これでroom.nameを変更したとき、対象roomのshowページを開いているブラウザが同時に更新されます。 room.playersとすることで、新しくroomに参加したplayerをリアルタイムで表示することも簡単にできますね。  

作ってみたもの

Hotwireを使って個人的に作ったものとしては、jsのドラッグ&ドロップライブラリをimportmapを使って読み込み、Stimulusを使ってTrelloのクローンを作ったり、Turbo Streamを使って、ブラウザ間の対戦ゲームを作ったりしました。 Rails 7でもHotwireを無理して使う必要はなく、必要になったタイミングで使っていくとよさそうです。

まとめ

Rails 7のHotwireを使うことで、依存関係の問題改善やjsのコード削減、SPAやWebsocketを使った開発などがかなりやりやすくなったと思います。 今回は簡単に紹介しましたが、複雑なこともできるので興味ある方はドキュメントを読んでみてください。 多くの新しい技術が使われているのではじめは抵抗あるかもしれませんが、全体像を簡単に理解して、必要に応じて使っていくと良いのではないかと思います。  

参考リンク

Turbo Handbook
Stimulus Handbook