Rails: HotwireとSPAを比較するなら実装コストの違いに注意(翻訳)
インターネット接続が遅い環境でHEYカレンダーのポップオーバーの読み込みが遅くなる様子が以下でツイートされたことがきっかけで、ポップオーバーのドラマが幕を開けました。その後、無慈悲で辛辣な書き込みやプロの荒らしの出現など、最もSNSらしい形で議論がヒートアップしました。
If you want to know why an app *needs* JavaScript on the client and can’t just do it all on the server, just look at Hey or any other Hotwrite app pic.twitter.com/RYbcNFeHXa
— Noah Falk (@noahflk) May 29, 2024
ここで面白い点は、このポップオーバーの例は、SPAとHotwire(HTML-over-the-wire)の議論を煽るのにも適していないほど的外れだったことです。実際には、以下のようにTurbo Frameを遅延プリロードするという小さな変更だけであっさり改善されました。
しかしより興味深い根本的な疑問は、「Hotwireは現代的かつ高度にインタラクティブなアプリケーションを作るのに適しているか?」です。答えは「おっしゃる通り」です。
カレンダーは、それだけで恐ろしく複雑な製品です。37signalsの小規模チームが10か月もかからずにゼロから作り上げたカレンダーは非常に出来がよかったため、多くの有料顧客がこのカレンダーの最初のバージョンをメインのカレンダーサービスとして選んでくれました。ポップオーバなどの応答性の問題への対応が優先されていなかったとすれば、顧客からのフィードバックに基づいて別の改善に取り組んでいたからです。現実は退屈なまでにシンプルでした。
さて、応答の速さや遅さを分析するときは、開発コストも加味しておかないと誤解の元になります。だからこそ、私がRails World 2023で私がTurboについて発表したときのスライド↓では、これを概念の中心に据えたのです。
縦軸: 応答性の高さ、横軸: 開発者の幸せ
参考: 37signals Dev — A happier happy path in Turbo with morphing
Hotwireが提供する多様な手法によって、開発コストの大小に応じてさまざまなレベルの忠実度(fidelty)を得られます。以下にHEYのカレンダーの実行例を3つ紹介します(このカレンダーはスペインのHEYに接続しています)。
- ToDo機能は、Turbo Streamsのアクションで追加する
- 日付タイトルの編集は、Turbo Framesで行う
- 新規イベントの追加とページ全体のレンダリングは、morphing(ページリフレッシュ)で行う
ご覧の通り、忠実度のレベルに応じてコストも異なります。Turboが非常に素晴らしいのは、段階的に実装を進められることです。つまり、最初は最も楽に開発できる方法にしておいて、後で必要に応じて変更できるのです。特に、上のポップオーバーの例で示したように、機能を段階的に改善して迅速にリリースできるのが強みです。Turboを使うことで、今後も改良を続けられることを確信できます。
TurboとSPAの開発モデルの比較については6年前に以下の記事に書きましたが、今も私の考えは当時と変わっていません。
参考: Escaping the SPA rabbit hole with modern Rails | by Jorge Manrubia | Medium
SPAは潜在的に優れた応答性を提供しますが、途方もなく高コストです。ここ数年、SPAがらみの恐ろしい話が原因でプロダクトが失敗したという話を数え切れないほど耳にしています。現実世界ではコスパがすべてであるにもかかわらず、多くのショップが(知ってか知らずか)コストを無視した技術スタックを選択しています。悲しいことに、このことでRailsやHotwireのプログラマーは大きなメリットを得ているのです。
ソフトウェア開発には、複雑さを売りにする人たちがいくらでもいます。そうした人々は、優れたエンジニアリング手法やローカルの最適化方法については饒舌ですが、そうした技術のコスパやシステム全体がどういう影響を受けるかについては何ひとつ教えてくれません。
上述の議論では「エンジニアリング」という言葉が多数飛び交っていましたが、私が申し上げたいのは、「コストから目をそむけるエンジニアはろくなものじゃない」ということです。
どうかコスト無視のエンジニアにはご用心ください。
概要
原著者の許諾を得て翻訳・公開いたします。
日本語タイトルは内容に即したものにしました。