前言
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
DHH(Ruby on Railsの作者)が、新しいものである「Hotwire」についてツイートしました。DHHはSPA(Single Page Application)の非推奨派(ツイートから推測できます)なので、JavaScriptをあまり使用しないように努めています。このツイートはTwitter上で活発な議論を引き起こし、ここでは少し整理します。
Hotwireの紹介については、公式の説明を引用します:
Hotwireは、JSONではなくHTMLをワイヤー上で送信することで、ほとんどJavaScriptを使用せずにモダンなWebアプリケーションを構築するための代替手法です。
この説明には2つの重要なポイントがあります:
- JavaScriptを必要としないこと
- JSONの代わりに直接HTMLを送信すること
実際、このコンセプトは最近になって登場したものではありません。数年前にRuby on Railsは同様の手法を採用しており、それが「Turbolinks」と呼ばれています。
Turbolinksとは?
Turbolinksは、通常Ruby on Railsと一緒に使用されるJavaScriptのライブラリです(単体で使用することもできます)。これは、HTMLを直接フェッチして置換することで、ページの再リクエストやCSSのコストを避けるためのものです。実際には「JavaScriptを必要としない」という表現は完全に正確ではありません。JavaScriptは存在しますが、ライブラリ側で処理が行われるため、開発者はJavaScriptを書く必要がありません。
例えば、以下のようなタグがページ上にある場合:
<a href="/articles/1" data-remote="true">リンク</a>
Ruby on RailsがTurbolinks機能を有効にしている場合、ユーザーがリンクをクリックしたとき、実際にはリクエストが再送信されるのではなく、Turbolinksが次のようなことを行います:
fetch('/index.html').then(res => res.html())
.then((html) => $page.html(html))
これにより、ユーザーがボタンをクリックしたときにHTMLを再レンダリングするのではなく、該当ページのHTMLファイルをフェッチし(Ajaxを介して)、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(Server-Side Rendering)の方法を使用し、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を直接レンダリングすることは、そんなに非難されることではありません。
ただし、現時点ではTurbolinksが最もRuby on Railsと統合されていると言えるでしょう。Hotwireは比較的新しいため、一部の開発者はまだ様子を見ているかもしれません。