Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
HotwireからDHHが考えるこれからのRailsとJSの付き合い方を知る
Search
Shinichi Maeshima
February 17, 2021
Technology
14k
14
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
HotwireからDHHが考えるこれからのRailsとJSの付き合い方を知る
「iCARE Dev Meetup #18」で発表した資料です
https://icare.connpass.com/event/201662/
Shinichi Maeshima
February 17, 2021
More Decks by Shinichi Maeshima
See All by Shinichi Maeshima
wkhtmltopdfの次どうするか問題2026
willnet
2
1.8k
メタプログラミングRuby問題集の活用
willnet
2
2k
rails g authenticationから学ぶRails8.0時代の認証
willnet
5
5.9k
What's a well-behaved Rails extension gem?
willnet
0
950
Sidekiq vs Solid Queue
willnet
15
15k
どうしてこうなった?から理解するActive Recordの関連の裏側
willnet
6
1.7k
Exceptional Rails
willnet
6
8.5k
Breaking the Flaky Test Cycle
willnet
2
2.6k
mrskで広がるインフラの選択肢
willnet
1
1.3k
Other Decks in Technology
See All in Technology
オブザーバビリティを高める AI エージェント体験を考える / Designing AI Agent Experiences That Enhance Observability
aoto
PRO
2
250
カンファレンスに参加した後の浮遊感とセルフケア
pauli
0
300
Claude起点の仕様駆動開発
tanakaseiya
0
320
More Freedom on the Same Shared GPU Cluster: A Small Team’s Experience with vCluster
nttcom
0
110
AI 時代の Azure エンジニアリング ~ 私たちは何を磨き、何を任せるのか ~
chack411
1
390
1人アドミンな私はAWSアカウント申請をSlackで完結したい!
ysuzuki
0
110
Execution in the Kingdom of Agents: Reflections on Abstraction and Complexity
bcantrill
0
770
データ品質を壊しながらSnowflakeのAIに分析させてみた
kawanago
0
460
[2026 Oracle Technical Deep Dive] エンタープライズAIエージェントを支えるOCIソリューション。ラインナップと特徴を理解しよう! (2026年9月17日開催)
oracle4engineer
PRO
0
320
生成AIを使って「人が」考える技術 ― AI時代の人機共想と実践ノウハウ|UNITT AC2026
ishiirikie
0
530
覗いてみよう 関数型ビジュアル言語×2Dグラフィックスの世界
yohyamasaki
0
170
プラットフォームを「作る」、 チームに「入り込む」
sansantech
PRO
0
630
Featured
See All Featured
The Hidden Cost of Media on the Web [PixelPalooza 2025]
tammyeverts
2
510
Building AI with AI
inesmontani
PRO
1
1.3k
Future Trends and Review - Lecture 12 - Web Technologies (1019888BNR)
signer
PRO
0
3.8k
Designing for Timeless Needs
cassininazir
1
510
Automating Front-end Workflow
addyosmani
1369
210k
How to audit for AI Accessibility on your Front & Back End
davetheseo
0
560
The B2B funnel & how to create a winning content strategy
katarinadahlin
PRO
1
550
Optimising Largest Contentful Paint
csswizardry
37
4k
We Have a Design System, Now What?
morganepeng
55
8.3k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
11
1k
Paper Plane
katiecoart
PRO
4
53k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
12
1.9k
Transcript
Hotwire から DHH が考えるこれからの Rails と JS との付き合い⽅を知る @willnet 1
いろんな会社で技術顧問をしつつ、空 いた時間で savanna.io などを開発して います 2
savanna.io は Hotwire を利⽤していま す 3
今⽇は Hotwire の話をします 4
Hotwire とは? Basecamp 社製js フレームワーク Rails の作者であるDHH がCTO をしている会社 hey.com(Basecamp
社製メールアプリケーション) を作るのに使われ ている 複数のフレームワークで構成されている 5
Hotwire とは? ( 意訳) モダンなweb アプリケーションを、JSON とたくさんの JavaScript を使うことなしに、HTML を送ることで実現するアプロー
チ Hotwire is an alternative approach to building modern web applications without using much JavaScript by sending HTML instead of JSON over the wire. “ “ 6
今どきの js フレームワークといえば JSON を使うのがふつう? サーバサイドはJSON を返す フロントエンドはJSON を受け取る そこからDOM
を構築してHTML をレンダリングする js ですべてを制御するのでUI を細かく作り込める 7
でもそれって⼤変ではないですか? ロジックがサーバサイドとクライアントサイド両⽅に必要になる クライアントは複数存在するのでそれぞれで実装を頑張らないと… ブラウザ iOS Android それぞれに専任のエンジニアが必要 8
Hotwire を使うとどうなるか サーバサイドにロジックを寄せることができる クライアントサイドのコードは最⼩限に抑えることができる それでいて、それなりにSPA ができる 結果として ひとつのチームですべてを担当できる( かも) 好きな⾔語を使える
Hotwire はRails に限らず使えるようになっている ※ブリッジになるようなものは必要(ex: turbo-rails gem) 9
とはいえ vue やreact と⽐べて細かいことはできない native アプリケーションも基本webview になるぞ hey.com (Basecamp 社製のメールサービス)
くらいのものであれば Hotwire で実現できるので、そのレベルで問題ないサービスならOK 「そのレベルで問題ないサービス」は結構な割合でありそう 10
Hotwire のアーキテクチャ Turbo Turbo Drive Turbo Frames Turbo Streams Turbo
Native Stimulus Strada( 現時点で未発表なので今回は話しません) iOS やAndroid のネイティブで必要な機能(ex: カメラ) とHTML と をつなげるためのライブラリらしい 11
前提 Hotwire はRails に限らず使えますが、Rails を前提にしたツール (turbo-rails) があるのでRails で使うのが便利です 今回はturbo-rails を利⽤している前提で話します
12
注意点 IE などの古いブラウザで動かすのは⼤変そう fetch API custom elements Intersection Observer API
など、モダンブラウザでしか動かないAPI を利⽤している polyfill を使えば動きそうだけど⼤変そう IOS も12 以上( 近いうちに13 以上) が必要 13
Turbo から話していきます 14
Turbo Drive Turbolinks を改善させたもの 15
Turbolinks とは Rails4.0 からRails 標準のライブラリとなっている すべてのリンクをajax で置き換える 受け取ったHTML のうち、body だけを現⾏のものと差し替える
するとjs やcss のダウンロード→ パースをスキップできるぶん⾼速化 できる 16
不遇の Turbolinks リリース当時( 約7 年前) はjQuery およびjQuery プラグイン全盛 Turbolinks はjQuery
プラグインと相性が悪いことがあった Turbolinks を使うためには⾊々わかっている必要があった 通常のページロードは最初の⼀回のみであること E2E テストで、次ページに遷移したかをちゃんと待つ必要がある form に関しては完全に対応していないこと ハマるひとが多く、デメリットが⼤きいと判断→ 基本消されるライ ブラリに 17
Turbolinks もきちんと理解して使えば 使いやすい いまはSPA なアプリケーションも増えたので、フロントエンドの知 識のある⼈も増えている( はず) 要点さえ押さえれば、少ない労⼒でSPA 化が可能なメリットは変わ っていない
18
( 余談 ) いま Turbolinks を使っているひと はどうやって Turbo に移⾏したらいいの エイヤで頑張ると移⾏できます
詳細はブログに書いたのでこちらを⾒てください Turbolinks からTurbo への移⾏ - おもしろweb サービス開発⽇記 19
Turbo Drive による改善 form に関してもデフォルトでturbo 仕様になった form_with ヘルパメソッドはこれまでTurbolinks を意識し、デフォ ルトで
data-remote="true" 属性がついていた Turbolinks を使っていない⼈からしたら混乱の元 Turbo がリリースされたことにより、Rails6.1 から data-remote="true" はデフォルトオフになった 20
Turbo Drive の form 送信時の挙動 form 送信時は302 などのレスポンスが返るとリダイレクト、4xx や 5xx
系が返るとレスポンスボディを差し替えて履歴はそのまま、と なった Turbolinks 時にここをちゃんとやろうとすると⼿動でSJR(Server generated javascript response) して対応する必要があった 21
SJR ってなに 例えばPost のcreate アクションでバリデーションエラーが起きたら、 次のようなposts/create.js.erb をレンダリングします。 (shared/_error.html.erb にエラーメッセージ⽤の部分テンプレートが ⼊っている想定)
document.querySelector('#error').innerHTML = "<%= j(render("shared/error", model: @post)) %>"; するとrails-ujs が↑ の内容をeval してくれるので <div id="error"></div> にエラーメッセージが表⽰されます。 22
SJR 、セキュリティどうなんですか さっき提⽰したコードのレベルなら⼤丈夫だけど、ユーザが⼊⼒し た⽂字列をカジュアルにSJR とすると⼤変危険ですね>< そもそもTurbo(links) でなにかするときに頻出する操作は限られて いる 特定のDOM にHTML
を挿⼊する(append, prepend) 特定のDOM を差し替える(replace, update) 特定のDOM を削除する これを提供するのがTurbo Streams 23
Turbo Streams Turbo のレスポンスとして、↓ のようなHTML ⽚を Content- Type=text/vnd.turbo-stream.html で返すとTurbo がいい感じに処理し
てくれる。 <turbo-stream action="append" target="messages"> <template> <div id="message_1"> id がmessages なDOM の内部に挿⼊(append) される </div> </template> </turbo-stream> 24
Turbo Streams で部分テンプレート活⽤ turbo-rails を使っていると次のように書ける turbo-stream タグやtemplate タグを⾃動で付与してレスポンスを返 す これで既存の部分テンプレートを活⽤できる!!
def create message = Message.create!(params.require(:message).permit(:content)) render turbo_stream: turbo_stream.append(:messages, # ここがturbo-rails 提供部分 partial: "messages/message", locals: { message: message }) end end 25
複数操作をする ビュー側で複数のturbo-stream タグをレンダリングして複数操作をす ることもできる <% # app/views/entries/entry.turbo_stream.erb %> <%= turbo_stream.remove
entry %> <%= turbo_stream.append "entries" do %> <%= render partial: "entries/entry", locals: { entry: entry } %> <% end %> 26
Turbo Streams で使える action action として使えるのは次の5 種類のみ append prepend replace
update remove レールを敷くことで判断を楽にできるのと、SJR でセキュリティに⽳ を開けるのを防ぐことができるのがメリット 27
Turbo Streams と websocket websocket(Action Cable) でも使える turbo-rails にはAction Cable
⽤のヘルパメソッドがあり、subscribe やbroadcast が簡単にできるようになっている 例えば新着メールが来たタイミングで⾃動的にメールが追加され る、というのが簡単にできる 詳細はturbo-rails ソースコードをみてください( 現時点でドキュメ ントにはほぼ記載がない) 28
ここまで⾒てわかる Turbo ができること 既存のHTML をそのまま使いつつユーザ体験を良くする(Turbo Drive) 同じテンプレートをいろんなところで使い回す(Turbo Stream) ex: ⼀通のメッセージを表す部分テンプレートをTurbo
Streams で も使う 29
もっと使いまわしたい いろんな環境で共通のテンプレートが使えるとうれしい スマホなどの⼩さい画⾯ PC の⼤きい画⾯ そこで Turbo Frames ですよ 30
Turbo Frames turbo-frame タグ中に書かれた要素はframe として区切られる frame 内のリンクはTurbo Frames ⽤のリンクとなる( 詳しくは次⾴)
<!-- messages/index.html.erb --> <body> <div id="navigation"> メッセージ⼀覧</div> <turbo-frame id="message_1"> <h1>Hotwire</h1> <p> いいですね</p> // ↓ をクリックすると… ? <a href="/messages/1/edit"> メッセージを編集する</a> </turbo-frame> </body> 31
Turbo Frames <!-- /messages/1/edit --> <body> <h1> メッセージの編集</h1> <!-- リンク元が
<turbo-frame id="message_1"> に含まれていれば ↓ の中⾝だけが差し替わる! それ以外のリンク元であれば ↑ のh1 タグ含めてbody 全体が差し替わる --> <turbo-frame id="message_1"> <form action="/messages/1"> <input name="message[name]" type="text" value=" メッセージタイトル"> <textarea name="message[name]"> メッセージの内容</textarea> <input type="submit"> </form> </turbo-frame> </body> 32
つまり Turbo Frames を使うとレスポンスのHTML の⼀部を使い、もとの HTML の⼀部を部分的に差し替えることができる 33
turbo-frame タグの中だけど普通のリン クにしたいときもありますよね <!-- messages/index.html.erb --> <body> <div id="navigation"> メッセージ⼀覧</div>
<!-- target="_top" とすると普通のTurbo のリンクとなる(body が全部書き換わる) --> <turbo-frame id="message_1" target="_top"> <h1>Hotwire</h1> <p> いいですね</p> <a href="/messages/1/edit"> メッセージを編集する</a> </turbo-frame> </body> 34
Turbo Frames のメリット target="_top" つけはずしすることで、⼀つのテンプレートを使いま わしできる ⼤きいディスプレイのときはインライン編集 スマホなどの⼩さいディスプレイでは専⽤のページに遷移させる 35
Turbo Frames のもう⼀つの活⽤⽅法 src 属性をつけると、値となるURL を⾮同期でfetch する ファーストビューの時間を短縮できる Turbo Frames
⽅式でレスポンスを差し替える <body> <h1> ともだち⼀覧</h1> <div id="friends"> ... </div> <h2> ともだちかも?</h2> <turbo-frame id="maybe_friends" src="/maybe_friends"> </turbo-frame> </body> 36
Turbo Frames でさらに遅延表⽰ loading="lazy" をつけると、その要素が画⾯に表⽰されるまでロー ドを遅延する <body> <h1> ともだち⼀覧</h1> <div
id="friends"> ... </div> <h2> ともだちかも?</h2> <turbo-frame id="maybe_friends" src="/maybe_friends" loading="lazy"> </turbo-frame> </body> 37
Turbo Native iOS やAndroid でTurbo を使うためのライブラリ webview でアプリケーションを利⽤する 主にTurbo Drive
での遷移による履歴をネイティブで管理するた めのもの 38
Turbo については⼀通り話した 39
Turbo を使うとサーバサイドにロジック が集中する つまりjs の量が減る が、ゼロになるわけではない Turbo を使うと、全ページで使うjs をひとまとめにして提供するよ うになる
js の整理がたいへん 「A というページでだけ発⽕させたいjs 」を管理するのがたいへん 40
Stimulus HTML とjs をいい感じに紐付け合い整理するライブラリ 学習コストが低い 41
42
特定のページだけで発⽕させたい js が 書きやすい // hello_controler.js import { Controller }
from "stimulus" export default class extends Controller { connect() { // ここにdata-controller="hello" が // 表⽰されたときに実⾏したい処理を書く } } 43
Stimulus のメリット controller ごとにファイルが⾃然と分かれて整理される HTML タグの属性名を⾒るとjs のどの部分に紐付いているかすぐわ かる 特定のページだけで発⽕させたいjs が書ける
44
まとめ 未公開のStrada を除き⼀通りHotwire について説明した Hotwire は、" 最⼩限の労⼒でユーザが求めているサービスを提供す ること" に特化しているライブラリ つまりそれはRails
と同じ⽅針をフロントエンドにも持ち込んだ、 と⾔える 少⼈数で開発するスタートアップ〜中規模なサービスに特に向い ているはず 便利なので使ってみてください! 45