第36章 Hotwire のアンチパターン
この章のねらい
第10部では、ここまで作ってきた Relay を振り返り、「Hotwire を選ぶべきか」を考えます。最初は、Hotwire を使うほど苦しくなる、典型的なアンチパターンです。
これらは、本書のあちこちで「使いすぎに注意」と触れてきたものの総まとめです。共通するのは、「できる」と「読みやすく保てる」を取り違えると、複雑さを抱え込む、ということです。
なお、この章が集めるのは構造・設計レベルのアンチパターンです。実装レベルの具体的な落とし穴(フォームの失敗を 422 ではなく 200 で返す=第8章・第25章、N+1=第30章、署名付き stream 名を認可と取り違える=第31章など)は、それぞれの章のアンチパターン節にまとめてあります。本章だけで落とし穴が尽きるわけではない、と捉えてください。
この部を貫く視点は「使える」ではなく「使い続けて保守できる」です。
36.1 すべてを Frame に入れる
Turbo Frames は便利なので、何でも frame で囲みたくなります。しかし、frame を増やすほど、入れ子が深くなり、「どのリンクでどこが差し替わるか」が追えなくなります(第14章)。
frame は、「ページの一部を、周りと独立して差し替えたい」ときの道具です。ページ全体が変わる遷移にまで frame を使うと、URL のズレや入れ子の複雑さだけを抱えます。1 か所の独立した更新に絞って使います。
36.2 controller が分岐だらけになる
「frame からのリクエストか」「Turbo Streams を返すか」で、controller が if 分岐だらけになることがあります(第14章)。
多くの場合、同じビューに frame を置いておけば、Turbo が必要な部分を取り出してくれます。まずは、リクエストの種類で分岐を増やさずに済まないかを考えます。分岐が増えてきたら、それは設計を見直す合図です。
36.3 Stimulus に状態管理を押し込む
Stimulus に、アプリの状態をため込みたくなることがあります。controller のインスタンス変数に、あれこれ持たせる形です。
しかし、Stimulus の状態は、Turbo がページや frame を差し替えると失われます(第21章)。状態は HTML 側(data 属性やクラス)に置き、サーバーが持つべき状態はサーバーに任せます。Stimulus は「振る舞いを足す小さな JavaScript」であって、状態管理の置き場所ではありません。複雑な状態管理が要るなら、それは Hotwire が向かない兆候かもしれません(第37章)。
36.4 broadcast が広すぎる
リアルタイム更新は強力ですが、配信先を広く取りすぎると、無関係なユーザーにまで更新が飛びます(第18章・第31章)。無駄な通信が増え、見せてはいけない情報が漏れる危険もあります。
配信先は、「その更新を見てよい範囲」に正確に合わせます。また、保存のたびに無条件で broadcast すると、回数が膨らみます(第30章)。「本当にリアルタイムで全員へ届ける必要があるか」を、その都度問います。
36.5 URL と画面状態が一致しない
frame や Stimulus で画面を作り込むほど、いま見えている状態が URL から復元できなくなりがちです(第14章)。リロードで状態が消え、共有しても同じ画面が出ず、戻る操作が期待とずれます。
主要な画面の状態は、URL に残します(data-turbo-action="advance" など)。URL は、Web の基本的な「場所」です。Hotwire を使っても、ここを壊さないようにします。
36.6 a11y を後回しにする
部分更新は、目で見ているユーザーには自然でも、スクリーンリーダーやキーボードのユーザーには伝わりにくいことがあります(第7部)。フォーカスが飛ぶ、更新が読み上げられない、といった問題です。
a11y を「後で」にすると、部分更新が積み重なった後では直しにくくなります。フォーカスの移動、aria-live での読み上げ、キーボード操作を、作るときから織り込みます。第7部の a11y チェックリストを、習慣にします。
36.7 通常の Rails に戻す判断
最後に、いちばん大事なアンチパターンへの対処です。Hotwire で無理をしていると感じたら、通常の Rails に戻す。
frame の入れ子と格闘している、controller が分岐だらけ、Stimulus に状態を詰め込んでいる。そんなときは、その画面が本当に Hotwire 向きだったかを問い直します。ふつうのページ遷移(Turbo Drive のまま)で十分なら、そこに戻すのが正解です。
判断の基準は、繰り返しになりますが、「できるか」ではなく「読みやすく保てるか」です。Hotwire は道具であって、目的ではありません。
第36章では、Hotwire のアンチパターンを総まとめしました。次の第37章では、視野を広げて、React / Vue などの SPA と Hotwire の使い分けを考えます。
参考資料
- Turbo Handbook(Building Your Turbo Application): https://turbo.hotwired.dev/handbook/building
- Hotwire: https://hotwired.dev/