ウェブ開発の世界は、ここ10年近くの大部分を、「ブラウザが重い処理を担うべきだ」と自分たちに言い聞かせることに費やしてきました。最初はドキュメントやフォームから始まり、その後、考えうるあらゆる操作が着実にクライアント側へと移行していきました。ルーティング、状態管理、データフェッチ、レンダリングロジック、さらにはGraphQLを通じたデータベースクエリのオーケストレーションに至るまで、そのすべてがJavaScriptバンドルへと移り、リリースごとにそのサイズは肥大化していきました。フレームワークは増殖し、ビルドパイプラインは複雑化し、アプリを軽快に感じさせるための手段として始まったものが、数メガバイトのコードがダウンロード、解析、実行されるまで、ページがたった1ピクセルすら意味のある形で描画できないようなアーキテクチャへと変貌してしまったのです。

この転換は、現実的な問題を解決しました。jQueryを少し添えただけのサーバーレンダリングされたページでは、ユーザーが期待するようなスムーズでアプリのような遷移を実現するのに苦労していました。Single Page Applications(SPA)は、瞬時のナビゲーション、永続的な状態、そして豊かなインタラクションをもたらしてくれました。しかし、その代償は蓄積されていきました。現在のチームは、複雑なクライアントサイドの状態ストアを管理し、巨大なJavaScriptバンドルを扱い、扱いにくいデータ同期レイヤーを維持し、時にはそれ自体がフルタイムの仕事のように感じられるビルドパイプラインのデバッグに追われています。私たちはある種の問題を別の問題へと交換してしまったのです。そして今、多くの開発者が「すべてのアプリケーションにそのコストを支払う必要があるのか?」と問い始めています。

その問いに答えを出しやすくしている2つの進展があります。

HTMXとハイパーメディアの回帰

1つ目はHTMXです。表面上は小さなライブラリに見えますが、そのアーキテクチャ上の意味合いは非常に大きいです。HTMXは、HTMLをJavaScriptによって展開されるべき静的なシェルとして扱うのではなく、アプリケーションロジックのためのネイティブなフォーマットとして扱います。

実務における変化は以下の通りです。従来、ユーザーが「もっとコメントを読み込む」ボタンをクリックすると、フロントエンドはfetchリクエストを送り、JSONペイロードを受け取り、それをクライアントサイドのストアに正規化し、コンポーネントテンプレートに通し、仮想DOMの差分を計算して、最終的にページにパッチを当てます。HTMXはこの連鎖をショートカットします。ボタン自体に、ブラウザに対して「どこにリクエストを送り、どのページ要素を置き換えるか」を指示する属性が含まれています。サーバーはHTMLフラグメント(単にdivで囲まれた新しいコメント部分)を返します。ブラウザはそれを入れ替えるだけです。そこにはJSONも、フロントエンドの状態ツリーも、リコンシリエーション・アルゴリズムも、UIをサーバーと同期させるための命令的なJavaScriptも存在しません。

これは現代的な開発を否定するものではありません。不必要な抽象化を否定するものです。HTMXは、初期のウェブを支えたアーキテクチャスタイルであるハイパーメディアが、現代的な使い勝手と組み合わせることで、今でも洗練されたインターフェースをサポートできることを証明しています。フォームやリンクだけでなく、あらゆる要素がリクエストを発行できます。あらゆるイベントが更新をトリガーできます。サーバーは、データとプレゼンテーションの両方における「信頼できる唯一の情報源(Source of Truth)」であり続けます。

ChromeのDeclarative Partial Updates

2つ目の変化はより新しく、ブラウザ自体の中に存在します。ChromeはDeclarative Partial Updates(DPU)を導入しようとしています。この機能により、ブラウザはHTMLをストリームとして受信し、バイトが届くたびにページの対象となる部分に直接挿入できるようになります。

DPUが登場する前は、ウェブページにライブデータをストリームしたい場合、一般的にWebSockets、Server-Sent Events、あるいは手動のDOM操作を組み合わせたロングポーリングを利用していました。フロントエンドは接続を管理し、ペイロードを解析し、マークアップを「どのように、どこに」注入するかを正確に決定しなければなりませんでした。DPUは、このプロセスを宣言的にすることで方程式を変えます。開発者がターゲットとなるコンテナを指定すれば、あとはブラウザがすべてを処理します。ストリームの受信、フラグメントの解析、そしてレスポンス全体が完了する前であっても、適切な場所への配置を正確に行います。

サーバーログを表示するモニタリングダッシュボードや、リアルタイムで更新されるサポートキューを想像してみてください。DPUを使用すれば、バックエンドは生成されたままのプレーンなHTMLチャンクを送信するだけです。ブラウザは、クライアントサイドのストリーミングロジックを一行も書くことなく、それらをテーブルの本体やフィードのコンテナへとストリームします。組み立てはネイティブに行われるのです。

サーバーファースト・モデル

HTMXとDPUを組み合わせると、サーバーが状態を所有してUIを生成し、ブラウザが表示とユーザー入力を処理するという、一貫性のあるアーキテクチャが得られます。Rails、Laravel、Django、Go templates、あるいはASP.NETといったバックエンドフレームワークが、再び主要なインターフェース層となります。フロントエンドは、APIを消費する独立したアプリケーションではありません。それは、サーバーが生成するハイパーメディア・インターフェースなのです。

このモデルは、驚くほど幅広い種類のソフトウェアに適合します。一般的なSaaSアプリケーションを考えてみましょう。それは、ソート可能なテーブルを備えたダッシュボードです。フォームやフィルターを備えた管理パネルです。レコードをある状態から別の状態へと遷移させる社内ツールです。リストを表示し、詳細ビューを提供し、ユーザーがフィールドを編集できるCRUDワークフローです。言語モデルがユーザーにトークンをストリーミングし、各トークンや段落をHTMLでラップして会話スレッドに追加できるAIインターフェースでさえもそうです。これらすべてにおいて、重厚なJavaScriptクライアントはしばしば過剰(オーバーキル)です。

メリットは即座に、かつ実用的です。ハイドレーション・サイクルが完了した後ではなく、最初の意味のある描画(First Meaningful Paint)がHTMLとして届くため、初期ページの読み込みが速くなります。仮想DOMも、クライアントサイドのルーターも、配信すべき状態管理ライブラリも不要になるため、JavaScriptのペイロードは削減されます。検索エンジンはバンドルを実行することなく完全なコンテンツを確認できるため、デフォルトでSEOが機能します。1つのコードベースでルーティング、ビジネスロジック、レンダリングを処理できるため、複雑さが軽減されます。デバッグも容易になります。何か問題があるように見えたら、Networkタブを検査して、サーバーが送信したHTMLを正確に確認できます。リバースエンジニアリングが必要な、不透明なクライアントサイドの状態オブジェクトも存在しません。

Reactや重厚なクライアントについてはどうなのか?

これがReactの終焉や、SPAが間違いであることを意味するわけではありません。複雑なエディタ級のアプリケーションには、依然として重厚なクライアントが必要です。Figmaは、サーバーとの往復通信では描画が不可能になるため、ブラウザ内でWebAssemblyにコンパイルされたC++エンジンを実行しています。Canvaは、クライアントサイドのジオメトリを使用して、キャンバスを毎秒60フレームで操作します。Google Docsは、オペレーショナル・トランスフォーム(OT)を使用して、ミリ秒単位で編集の競合を解決します。これらのツールは、本質的にはブラウザのタブを通じて提供されるデスクトップアプリケーションです。これらがサーバーレンダリングされたフォームに戻ることはありません。

しかし、ほとんどのソフトウェアはFigmaではありません。ほとんどのソフトウェアは、リアルタイムのグラフィックスエディタではありません。ほとんどのソフトウェアは、レポート画面、設定パネル、予約フロー、あるいはコンテンツ管理フォームです。そのようなロングテールなアプリケーションにおいて、モーダルを切り替えたりレコードのリストを取得したりするためだけに、数百キロバイトものJavaScriptフレームワークを配信することは、これまで一度も理にかなったことはありませんでした。スタックの経済性が変化しています。エッジのおかげでサーバーがユーザーの近くに配置できること、そしてブラウザ自体が、すべてのバイトにフレームワークを介在させることなく断片を更新できるほど十分に進化していることを、私たちは再発見しています。

振り子が均衡を見出す

ウェブアーキテクチャの弧はシンプルさへと戻りつつありますが、それは90年代へのナイーブな回帰ではありません。ブラウザはよりスマートになっています。DPUのような機能は、開発者の創意工夫に取って代わるものではありません。それらは、私たちがかつて手動で実装していたパターン(ストリーミング、部分的な更新、ターゲットを絞ったDOM挿入など)を、プラットフォーム自体に吸収させているのです。HTMXは、フロントエンドにミニチュアのオペレーティングシステムを再構築することなく、それらの振る舞いを表現するための語彙を私たちに提供してくれます。

シンプルなアーキテクチャとレスポンシブなユーザーエクスペリエンスの間で、もはや選択する必要はありません。両方を手に入れることができます。サーバーがインターフェースを駆動し、ブラウザがそれを組み立て、あなたが書くJavaScriptは、配管作業(plumbing)ではなく、真のインタラクティビティに集中できるのです。

次世代のダッシュボード、管理ツール、そしてAI搭載インターフェースにとって、最もスマートなクライアントとは、あえて「より少ないことしかしない」クライアントなのかもしれません。