質問やフィードバックがありましたら、フォームからお願いします
本文は台湾華語で、ChatGPT で翻訳している記事なので、不確かな部分や間違いがあるかもしれません。ご了承ください
前言
Hotwire aka NEW MAGIC is finally here: An alternative approach to building modern web applications without using much JavaScript by sending HTML instead of JSON over the wire. This includes our brand-new Turbo framework and pairs with Stimulus 2.0 😍🎉🥂 https://t.co/Pa4EG8Av5E
— DHH (@dhh) December 22, 2020
Ruby on Railsの作者DHHが新作Hotwireについてツイートをしました。DHHはSPAに対して批判的であることが伺えます(ツイートからわかるように)。そのため、彼は開発に多くのJavaScriptを取り入れることを極力避けています。このツイートはTwitter上で大きな反響を呼び、ここで少し整理してみます。
Hotwireの紹介については、公式の説明をそのまま引用します:
Hotwire is an alternative approach to building modern web applications without using much JavaScript by sending HTML instead of JSON over the wire
この説明には二つの重要なポイントがあります:
- JavaScriptを使用する必要がない
- HTMLを直接送信し、JSONではない
この概念は最近始まったものではなく、数年前からRuby on Railsでは似たような手法が採用されており、Turbolinkという名前で知られています。
Turbolinksとは?
TurbolinksはJavaScriptのライブラリで、通常はRuby on Railsと一緒に使用されます(単独でライブラリとしても利用可能です)。主にfetch HTMLを用いてページ遷移の際に再度リクエストを送信するコストやCSSのコストを回避します。「JavaScriptを使用する必要がない」と言うのは完全に正しいわけではなく、JavaScript自体は存在しますが、ライブラリがその処理を行っているため、開発者はJavaScriptを書く必要がないだけです。
例えば、ページ上に以下のようなタグがあるとします:
<a href="/articles/1" data-remote="true">link</a>
もしRuby on RailsでTurbolinks機能が有効になっている場合、ユーザーがリンクをクリックすると、実際には新たにリクエストを送信するのではなく、Turbolinksが次のような処理を行います:
fetch('/index.html').then(res => res.html())
.then((html) => $page.html(html))
これにより、ユーザーがボタンをクリックした際、HTMLが再レンダリングされるのではなく、まずそのページのHTMLファイルを(Ajaxを介して)fetchし、その後JavaScriptを使ってレンダリングされます。Ruby on Rails自体とTurbolinksは高度に統合されているため、時にはTurbolinksの存在をほとんど感じることなく、「ページ遷移が速くなった」と感じることがあります。
HTMLが大きくなるほど、その効果は薄れていくと思われますが、HTML自体がそれほど大きくなければ、より良いユーザー体験を得ることができます。
なぜこの方法が有効なのか?
- ページ遷移時にCSSやJavaScriptのリクエストを再送信する必要がなく、ユーザー体験が向上する
- head部分の処理をTurbolinksが行ってくれる
- 追加のJavaScriptを書く必要がほとんどない
- バックエンドエンジニアが最小限の労力でより良い体験を実現できる
注意すべき点
load
のようなイベントは、Turbolinksのメカニズムによりページ全体が再読み込みされないため、初回の読み込み時にのみトリガーされます。イベントを監視するにはturbolinks:load
のように切り替えることを忘れないでください。- JavaScriptのインタラクションが増えると、イベントのバインディングが衝突しやすくなります。
- ページ遷移時に状態が消去されないため、JavaScriptが適切に記述されていないとメモリリークを引き起こす可能性があります。
JavaScriptのインタラクションが増えると、Turbolinksと組み合わせた際に奇妙な現象が発生することがあり、例えば重複実行によるエラーなどが見られます。
一部の考え
開発者として、少なからずSPAを作成した経験があると思います。誰もが実用的で使いやすいSPAを作ることが簡単ではないことを知っています。状態管理がうまくいかずメモリを大量に消費したり、状態が同期しなかったり、エラーハンドリングが不十分だったり、JavaScriptバンドルを大量に読み込むことになったりすることがあります。そのため、むしろ純粋なSSRを利用してレンダリングする方が良い場合も多く、Turbolinksのような方法で体験を向上させることは良いアプローチかもしれません。
後記
It’s fucking hilarious that the tagline of this is “Hotwire is an alternative approach [...] by sending HTML instead of JSON over the wire”
— Surma (@DasSurma) December 22, 2020
HTML INSTEAD OF JSON? BLOODY MADNESS!
Then again, if this makes “sending HTML over the wire” popular, I’ll take it. https://t.co/7bLGdtJn7u
A lot of folks think serving JSON is more efficient than HTML, but once gzipped they're often the same. Sometimes HTML is smaller.
— Jake Archibald (@jaffathecake) November 15, 2017
Eg https://t.co/hgxyH0N3Ct:
JSON: 18k.
Generated HTML: 17k.
Also, it's much easier to stream HTML & get a progressive render.
多くの人はJSONがHTMLよりも効率的に見えると思っていますが、gzip圧縮後は実際には同じくらいのサイズになることが多いです。時にはHTMLの方が小さいこともあります。したがって、HTMLを直接レンダリングすることは決して悪いことではないように感じます。
ただし、現在のところTurbolinkが最も統合されているのはRuby on Railsであり、Hotwireは比較的新しいため、一部の開発者はまだ様子を見ているかもしれません。
この記事が役に立ったと思ったら、下のリンクからコーヒーを奢ってくれると嬉しいです ☕ 私の普通の一日が輝かしいものになります ✨
☕Buy me a coffee