Hotwireの基本と導入手順 Rails7
Hotwireとは
Hotwireとは、Rails7からスタンダードになったフロントエンドのフレームワークです。
基本的にRailsは、ページ遷移のたびにサーバーサイドからHTMLを取得してレンダリングするMPA(Multi Page Application)という形式ですが、このHotwireをうまく使用するとReactやVueのような、1つのHTMLページ内で動的にコンテンツを切り替えるSPA(Single Page Application)風なアプリケーションの作成が行えます。このHotwireと呼ばれるフレームワークは、次の三つの技術が合わさって構築されています。
①Turbo
→Hotwireの中核となるJavaScriptのライブラリでページの一部だけを非同期で更新する機能を搭載しています。
②Stimulus
→軽量なJavaScriptフレームワークでサーバーサイド駆動のインタラクティブなUIを実現します。そして、技術的負債になりがちなJavaScriptファイルにcontrollerという単位を持たせることで管理しやすくしています。
③Strada
→スマホアプリ用のライブラリでネイティブアプリとWebViewの連携を強化する予定になっています。まだ、開発中の技術になっています。
今回は、webアプリへのHotwire導入になるので主に扱う技術としては、①のTurboと②のStimulusについてです。
Turbo
Turboは、分解すると下記三つのモジュールの集合体です。
①Turbo Drive
このTurbo Driveは、画面遷移を高速にしてくれるTurboの機能です。主にやっていることは、リンクやフォームのリクエストをTurbo Driveがインターセプトして、fetchによる非同期リクエストに差し替えるということです。そして、レスポンスとしてhtmlのbody要素だけを置換します。そのため、通常の画面遷移よりも高速な処理を実現します。
このTurbo Driveは導入するだけで、この恩恵を受けられるのが特徴です。
②Turbo Frames
Turbo Framesは、Turbo Driveの部分置換版です。Turbo Driveがbody要素を置換するのに対して、Turbo Framesは<turbo-frame>...</turbo-frame>
というhtmlで囲んだ箇所のみ置換してくれます。
③Turbo Streams
Turbo Streamsは複数箇所のHTML要素を同時に更新できます。先ほど紹介したTurbo Framesで更新できるのは<turbo-frame>
で囲った1箇所だけという制約があるため、複数箇所の同時更新となるとこのTurbo Streamsを使うことになります。さらに、Turbo StreamsではHTML要素の追加・更新・削除をすることも可能になります。
Stimulus
Stimulusは、軽量なJavaScriptのフレームワークでRailsのフロントエンドをインタラクティブにするのに使います。
では、Turboと何が違うの?と思った方もいると思います。Turboは、Railsの7つのアクションにおいてjavascriptを一切書かずに対応することができるもので、それ以外にRailsのフロントエンドをインタラクティブにしたい時に使用するのがStimulusです(7つのアクション以外でJavaScriptを使いたい時)。
このStimulusの特徴は、JavaScriptのファイルをcontrollerという単位で管理することです(Railsっぽい、、)。大体カオスになりがちなJavaScriptのファイルにルールを与えて可読性や保守運用性を高めてくれます。
ここまででHotwireの基本概念を伝えることができたと思うので、ここからは実際にRailsに導入していく手順を紹介します。
Hotwireの導入手順
今回は、Rails7から導入されているimport mapsというwebpackやesbuild等のバンドラーを利用しないでCDNでJavaScriptライブラリを取得する方法を使っていく。
そのため、まずはまだ実現場では馴染みのない、import mapsについて詳しく説明していきます。
import mapsについて説明できた後、Hotwireの導入を行なっていきます!
import mapsとは
まず、Rails7からJavaScriptの管理方法として導入されたimport maps
について説明します。このimport maps
の最大の特徴は、webpackやNode.jsなどを使わずにCDNで必要なライブラリを取得できる点です。これは、これまでのRails6で使われていたwebpackなどのバンドラーやサーバーサイドでjavascriptを実行するためのnode.jsなどを使用してビルドする必要がありません。
そのため、import maps
はビルドせずにjavascriptをフロントエンドのみで扱えるのでシンプルで環境構築が非常に楽なのが特徴です。
import mapsの導入
import mapsの有効化
Rails7からは、このimport mapsがデフォルトで有効化されています。
もし、Rails6などでimport mapsを使用したい場合は、下記コマンドで有効化することができます。
bin/rails importmap:install
このコマンドを実行するとconfig/importmap.rb
というファイルが作成されます。
このファイルにCDN形式で必要なJavaScriptライブラリを導入していきます。
Turbo & Stimulusの導入
turboとStimulusの導入は非常に簡単です。
Rails7のデフォルト設定では、turbo-railsとstimulus-railsをGem経由でインストールすると、必要なJavaScriptライブラリがimportmapに自動登録されるようになっています。
なので、import mapが有効になっていることを確認して、下記gemをGemfileに追加し、bundle installを行います。そして、最後にturboとstimulusのインストールを実行するとimportmap.rbに必要な記述が追加されています。
①Gemfileに追加
gem "turbo-rails"
gem "stimulus-rails"
②bundle installを実行
bundle install
③turboとstimulusのインストール
rails turbo:install
rails stimulus:install
config/importmap.rbで確認
rails turbo:installやrails stimulus:installを実行すると、config/importmap.rbにCDNのライブラリが登録されるので、確認してみましょう。
pin "application"
pin "@hotwired/turbo-rails", to: "turbo.min.js" # Turbo を登録
pin "@hotwired/stimulus", to: "stimulus.min.js" # Stimulus を登録
pin_all_from "app/javascript/controllers", under: "controllers" # Stimulus のコントローラを登録
おそらく、上記のような登録が行われていると思います。
特にカスタム設定を行いたい場合以外はこれで問題ありません。
Turbo & Stimulus が正しく動くか確認する
app/javascript/application.js
をチェックし、次のようになっていればOKです。
import "@hotwired/turbo-rails"
import { Application } from "@hotwired/stimulus";
import { eagerLoadControllersFrom } from "@hotwired/stimulus-loading";
const application = Application.start();
eagerLoadControllersFrom("controllers", application);
Stimulus のコントローラを作成
Stimulusが正しく動くか試すために、テスト用のコントローラを作ってみましょう。
rails generate stimulus hello
app/javascript/controllers/hello_controller.js
import { Controller } from "@hotwired/stimulus";
export default class extends Controller {
connect() {
console.log("Hello, Stimulus!", this.element);
}
}
view側には下記のようにdata-contorllerにコントローラ名を追加することでstimulusのコントローラファイルが実行されます。
<div data-controller="hello">
Hello, world!
</div>
これでコンソールにHello, Stimulus!
と表示されたら正常に動作しています!
Discussion