Share
Embed
ハイパーメディア駆動アプリケーションとIslandアーキテクチャ: htmxによるWebアプリケーション開発と動的UIの局所的適用
このスライドはフロントエンドカンファレンス関西2025で使用したものです。
---
ハイパーメディア駆動アプリケーション(HDA)アーキテクチャは、従来のマルチページアプリケーション(MPA)の単純さと柔軟性に、シングルページアプリケーション(SPA)の操作体験を取り入れる設計アプローチです。本セッションの前半では、HDAの設計思想に基づく実践例として、htmxを用いたWebアプリケーションの画面遷移や状態更新の設計手法を具体的に紹介します。後半では、局所的な動的振る舞いが求められる場面において、Islandアーキテクチャを取り入れて補完する方法とその設計上の工夫について考察します。
Ryota Nakamura
November 29, 2025
Transcript
49 slides
-
中村遼大 / @nowaki28 • フロントエンドエンジニア • 普段はReactを主に使用 • 最近ハマっているもの: 遊戯王マスターデュエル
• カービィのエアライダーを早くやりたい 自己紹介 -
SPA: Single Page Application > An SPA (Single-page application) is
a web app implementation that loads only a single web document, and then updates the body content of that single document via JavaScript APIs such as Fetch when different content is to be shown. https://developer.mozilla.org/en-US/docs/Glossary/SPA • def: よくあるSPA ◦ リロードを伴わないナビゲーション( JavaScriptによるルーティング) ◦ JSONを介してAPIサーバと通信 ※以降このセッションでは SSR/SSGされたものも含めてSPAと定義します →現代Webアプリケーションのデファクトスタンダード -
~2000年代前半 静的なHTMLやCGIが中心 • ホームページ・ビルダー • CGI • RESTの誕生(2000年) ◦ 当時はRPC的な設計が主流
https://web.archive.org/web/19981206015551/http://village.infoweb.ne.jp/~fwgj3966/ https://web.archive.org/web/20031204192728/http:// news4.2ch.net/news/#1 -
2000年代後半~2010年代前半①: 「Webアプリケーション」へ 次第にデスクトップアプリに近いUXが求められるように • 当初のリッチなクライアントの実現方法 ◦ Java Applet ◦ ActiveX
◦ Flash → 非標準の技術に依存 • 互換性の問題 • プロプライエタリなプラットフォーム (特定企業による独占) -
HTML5(2008にドラフト発表)によりWeb標準だけでもリッチなWebアプリが実装可能に • Flashなどで実現していた機能がこの時期にWeb APIとして標準化された ◦ 例(他多数) ▪ <video>/<audio> ▪ <canvas>
▪ File API ▪ Drag and Drop API • MVCフレームワークが普及, jQuery全盛期 • AJAXを使用したWebアプリケーションが広まる • iPhoneのFlash非サポート →FlashからHTML5へ移行する流れへ 2000年代後半~2010年代前半②: HTML5 https://blog.google/products/maps/look-back-15-years-mapping-world/ -
2010年代前半~: SPAフレームワークの台頭 • Backbone.js, AngularJSのようなフレームワークの台頭 →後にReact, Vue, Svelteなど • ES6の標準化でJavaScriptの使い勝手が向上
→ 大規模Webフロントエンドが開発しやすい土壌が整ってきた -
SPAの優れていたところ • SPAは当時の一般的なMPAよりUXが優れていた • 従来のWebアプリケーションはMPA(Multi Page Application)と呼ばれるように 遷移速度 更新 UIの状態
MPA ❌遷移ごとに初期化が必要 ❌ページ全体のリ ロードが必要 ❌失われる SPA ⭕クライアントで完結したルー ティング・ナビゲーション ⭕関連するDOMのみ 更新 ⭕保持される MPA SPA -
2010年代終盤~: メタフレームワークの時代へ • SPAをSSR/SSGするためのメタフレームワークが浸透 ◦ SPA = CSRだった時代から、サーバ・クライアントサイドどちらでもコードが実行されるよ う に
▪ レンダリング: CSR, SSR, SSG, ISR/Streaming SSR,Partial Prerendering ▪ Hydration/Resumable(Qwik): レンダリング済みHTMLを返した後の状態復元やイベントハンドラのアタッチ → SPAの弱みとなっていた部分を解消 -
SPA + メタフレームワークによって失われたもの メタフレームワークは確かに高機能で、 SPAに関する様々な問題を解決したが Webそのもののシンプルさが代償となった • 複雑さの増加 ◦ フレームワークの中で何が起きているのか全てを理解するのは難しい
(ブラックボックス化) ◦ 複数の実行環境(Server/Edge/Browser)と複数の実行タイミング (build/request/stream/hydrate) ▪ デバッグ・トレースに要求される前提知識の増加 • 学習コストの増加 ◦ 2000’s: HTML, CSS, JavaScript + jQuery ◦ 2010’s: HTML, CSS, JavaScript + React, Webpack ◦ 2020’s: HTML, CSS, JavaScript + React + Next.js = Rendering, Server/Client Component, Routing, Fetch strategy, Cache layer, Module Bundler, Deployment(Vercel/Netlify/CloudFlare Workers,…etc) • フレームワークへのロックイン ◦ シンプルなSPA時代よりも依存する範囲が拡大 ◦ フレームワークのアップデートに追従し続ける必要 ◦ 性能を最大限に引き出すには特定ホスティングサービスへのデプロイが前提(セルフホスティングは可能だがメンテナンスコスト 増) -
MPAはシンプルだが、以下のような欠点があった →逆に言えば、これらさえ克服できれば MPAで十分(高度なFWはtoo much)なケースもありそう 遷移速度 更新 UIの状態 MPA ❌遷移ごとに初期化が必要 ❌ページ全体のリ
ロードが必要 ❌失われる MPA 振り返り: なぜMPAのままではダメだったのか -
REST: Representational State Transfer Roy T. Fieldingの博士論文: Architectural Styles and
the Design of Network-based Software Architectures (2000)で提唱されたアーキテクチャ・スタイル • §5.1 Deriving REST 分散ハイパーメディアシステムに必要な性質(スケーラビリティ、汎用性、独立進化、低結合など)から、求 められる制約(constraints)を導出→REST ◦ クライアント/サーバ ◦ ステートレス ◦ キャッシュ ◦ レイヤードシステム(プロキシ) ◦ 統一インターフェース ◦ コードオンデマンド(optional) source: https://roy.gbiv.com/pubs/dissertation/fielding_dissertation.pdf - Roy T. Fielding(2000) Roy T. Fielding https://roy.gbiv.com/ -
統一インターフェース(Uniform Interface) RESTのUniform Interfaceは以下の4つのインターフェース制約によって定義される : • リソースの識別 ◦ 具体的には: URIによるリソースの識別
• 表現を通したリソース操作 ◦ 具体的には: HTML/JSONのような表現の送受信でリソースを操作する • 自己記述的メッセージ ◦ 具体的には: HTTPヘッダ等によるメタ情報 • アプリケーション状態のエンジンとしてのハイパーメディア -
アプリケーション状態のエンジンとしてのハイパーメディア • アプリケーション状態: クライアント側で保持される「現在どこにいるか、何をしているか」という状態 • クライアントは、サーバから返されるハイパーメディアの中に含まれるリンクや フォームを使ってアプリケーション状態を遷移させる ◦ サーバ側の URI・遷移ロジックを変更してもクライアントは壊れない
(バージョニング不要) →こんにち我々がREST APIと呼んでいるJSON API ≠ REST (むしろFieldingが批判していたRPCに近い) HATEOAS: Hypermedia As The Engine Of Application State -
MPA vs SPA MPAはRESTに適合しやすかったが、SPA以降のWebはRESTではなくなった (紆余曲折ありJSON APIをREST APIと呼ぶ誤用が定着) https://htmx.org/essays/how-did-rest-come-to-mean-the-opposite-of-rest/ MPA SPA
アプリケーション状態 HTMLによって駆動 JavaScript若しくはJSONによって駆動 -
ハイパーメディア駆動アプリケーション https://htmx.org/essays/hypermedia-driven-applications/ • RESTの制約に従うWebアーキテクチャ ◦ 命令型のスクリプトではなく宣言型の HTML埋め込み構文を使用 ◦ 非ハイパーメディア形式( JSONなど)ではなく、ハイパーメディア
(HTMLなど)でサーバーと対話 →MPAにSPAの体験を取り入れるアプローチ • 主なライブラリとしてはhtmx(後述), hotwire(Rails)など HDA: Hypermedia Driven Application 『ハイパーメディアシステム ─ ─htmxとRESTによるシン プルで軽やかなウェブ開発』技術評論社 https://gihyo.jp/book/2025/978-4-297-14945-1 -
Fact: HTML/CSS自体も表現力が向上している 例: • モーダルウィンドウ: <dialog> • アコーディオン: <details>/<summary> •
フォームバリデーション/自動補完 • 遷移アニメーション: View Transitions API • コンポーネント化: Custom Elements/Declarative Shadow DOM -
• MPAのナビゲーションが抱える問題は依然として解決していない → HATEOAS的設計を守りつつ、これらの課題を解消するのが現代的なHDA 遷移速度 更新 UIの状態 MPA ❌遷移ごとに初期化が必要 ❌ページ全体のリ
ロードが必要 ❌失われる MPA とはいえ素のHTMLだけでは流石にまだ足りない -
> htmx gives you access to AJAX, CSS Transitions, WebSockets
and Server Sent Events directly in HTML, using attributes, so you can build modern user interfaces with the simplicity and power of hypertext > Why should only <a> & <form> be able to make HTTP requests? Why should only click & submit events trigger them? Why should only GET & POST methods be available? Why should you only be able to replace the entire screen? By removing these constraints, htmx completes HTML as a hypertext https://htmx.org • AJAXでHTMLを取得して更新(i.e. サーバ主導で状態を更新): →HATEOASを実現 • HTMLに足りない表現力を拡張するというコンセプト : →必ずしもJavaScriptを書く必要がない • 既存MPAに導入しやすい 公式ドキュメントのUI実装サンプル: https://htmx.org/examples/ -
htmx: hx-*属性(抜粋) hx-*属性によってUIの振る舞いを定義 • hx-trigger: click, changedなど、イベントをトリガする条件 ◦ delayやthrottleなども制御可能 •
hx-get(hx-post,hx-put,…etc): GET(POST/PUT…etc)リクエストを行う • hx-target: Ajaxレスポンスによって更新する対象の要素(クエリセレクタ) • hx-swap: Ajaxレスポンスによって更新する方法 ...innterHTML/outerHTML, 前後など • hx-select: Ajaxレスポンスのうちどこを使うか → i.e. リクエストする側で指定できるのでサーバはHTML断片を返してもフルのHTMLを返しても良い ←ユーザーがこのボタンをクリックすると、 HTTP POSTリクエス トを “/clicked” に発行し、id=”parent-div”のDOM要素をレスポ ンスの内容に置き換える https://htmx.org/docs/#introduction -
今時MPAは作りたくない → ReactだけだとSEOなどの問題 → Next.jsを採用... ↑のような理由だけで本来不要な複雑さを持ち込むのはもったいない MPA/SPAの二択だけでは無い シンプルさ UX 高度なインタラクション
MPA ⭕ ❌ ❌ SPA ❌ ⭕ ⭕ HDA ⭕ ⭕ 🔺 -
本当に必要なものは何? htmx(HDA)はNext.jsのような高機能なフレームワークに取って代わるようなものではな いが... • 本当に以下のようなWebアプリをNext.jsで作ってVercelにデプロイする必要があり ますか? ◦ 管理画面的なやつ ◦ 静的コンテンツ中心のサービス
◦ CRUD中心の業務アプリ ◦ 設定画面・運用ツール ◦ 非リアルタイムなダッシュボード ◦ フォーム主体のアプリ • 動的要素が中心ではなく、SPA的な体験が必要なだけであれば MPA(HDA)も選択肢に 例: Next.js -> honoX(オススメ!) + htmxで十分かもしれない -
htmx + 動的UIの問題点 一部の領域だけクライアントライブラリが状態を持っている UI • htmxはDOMを直接差し替えるので、クライアント側の状態やイベントハンドラのアタッチがリ セットされてしまう • JSX中のDOMを直接Swapした場合、ReactのようなVirtual
DOMを持っているフレームワーク では競合する(外からまるごと更新するのであれば問題無い) -
Shadow DOMに隔離する = Custom Elements化 https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_shadow_DOM • Shadow DOM: 外側と分離されたDOM
スコープ <-> Light DOM • 基本的にはホスト側から内部の構造を見たり触ったりできない • <slot>で内側にLight DOMを配置することもできる https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_shadow_DOM#high-level_view -
htmxの領域をWeb Componentでラップする • Shadow DOMの中をhtmxで更新してもホスト側には影響しない ◦ slotを使用しすればReact → htmx →
Reactというツリー構造も可能 • connectedCallbackでhtmx.process(ShadowRoot) ◦ ShadowDOMのツリーだけhtmxを適用しているのでホスト側に影響しない Shadow DOMに隔離する = Custom Elements化