/note/tech

How Functional Programming Shaped (and Twisted) Frontend Development

要約:

■ 1. 友人の衝撃と問いかけ

  • 10年以上ぶりのフロントエンド: バックエンドとインフラに移行していた友人が現代のReactコードベースを初めて開いた
  • 衝撃の反応:
    • 「これは一体何だ?」
    • 「生成されたクラス名は何?」
    • 「カスケードをキャンセルしたのか?」
    • 「誰がWebをこんな風に動かすようにしたんだ?」
  • 彼の記憶: CSSが自然にカスケードし、DOMと協働し、ブラウザがルーティング・フォーム・イベントを20の抽象化なしで処理していたWeb
  • 彼の印象: 現代のフロントエンドスタックはプラットフォーム自体に戦争を宣言したように見える

■ 2. 著者の背景

  • 第一次ブラウザ戦争を生き抜いた: IE6で24ビットPNGを動かすためにpngfix.jsを適用
  • 2AMのデバッグ: hasLayoutバグをデバッグ
  • addEventListenerが信頼できない時代: ブラウザ間で同じように動作しないJavaScriptを書いていた
  • jQueryの変遷: 必要になり、不可欠になり、レガシーになるのを見た
  • バイアスの自覚: 間違っているかもしれないし、バイアスがあるのは確か。だがWebは絶え間ない再発明なしに有用だったという記憶も持っている

■ 3. 奇妙な皮肉:Webの本質と関数型プログラミングの衝突

  • Webの起源: ドキュメント、ハイパーリンク、カスケードスタイルシート言語から生まれた
  • Webの特性: 常に乱雑で、可変的で、栄光的に副作用だらけ
  • 過去10年の影響: 最も影響力のあるフロントエンドツールは、関数型プログラミングの純粋性を追求するエンジニアによって形作られた
  • FPの理想: 不変性、決定論、副作用の排除
  • 得たもの: 強力な抽象化。Reactはコンポーネントで考えることを教えた。Reduxは状態変更を追跡可能にした。TypeScriptは動的言語にコンパイル時の安全性をもたらした
  • 失ったもの: 奇妙な道を進んだ。プラットフォームを受け入れる代わりに戦った。ブラウザのネイティブ機能をJavaScriptで再構築し、DOMから「保護」するために何層もの間接層を追加し、Webの本質的な乱雑さは理解すべき特徴ではなく解決すべき問題だと自分たちを納得させた

■ 4. Webの本質

  • 根本的に副作用だらけ:
    • CSSは設計上グローバルにカスケードする
    • 一箇所で定義されたスタイルがどこでも要素に影響を与え、特異性と継承を通じて創発的パターンを作る
    • DOMは巨大な可変ツリーで、ブラウザが執拗に最適化している
    • 直接変更するのが高速で予測可能
  • ユーザーインタラクション: 非同期で予測不可能に到着する(クリック、スクロール、フォーム送信、ネットワークリクエスト、リサイズイベント)。「ユーザーの意図」を捉える純粋関数は存在しない
  • 乱雑さは偶然ではない:
    • これがWebが何十億ものデバイスにスケールする方法
    • 何十年にもわたって後方互換性を保つ方法
    • 異種システムが相互運用できる方法
  • ブラウザはオープンプラットフォーム: どこにでもエスケープハッチがある。何でもスタイルでき、どのイベントにもフックでき、どのノードも操作できる。この柔軟性と厳格な抽象化の強制を拒否することがWebのスーパーパワー
  • FP本能での認識: この柔軟性を混沌と見る。グローバルを危険と見る。変更を予測不可能と見る。副作用を待ち構えているバグと見る。だから壁を作る

■ 5. 関数型プログラミングの理想の侵入

  • FPのコア原則:
    • 関数は純粋であるべき(同じ入力→同じ出力、副作用なし)
    • データは不変であるべき
    • 状態変更は明示的で追跡可能であるべき
    • 適切な文脈では、推論・テスト・並列化が容易なコードを生成
  • React以前からの浸透:
    • Underscore.js(2009): map、reduce、filterを大衆にもたらした
    • LodashとRamda: カリー化、合成、不変性ヘルパーを含むより深いFPツールキット
    • 空気中のアイデア: 変更を避け、小さな関数を合成し、データ変換をパイプラインとして扱う
  • Reactの進化:
    • 最初はクラスコンポーネントとsetStateで、純粋なFPとは程遠い
    • しかし概念的基盤はあった: UIを状態の関数として扱い、レンダリングを決定論的にし、副作用を分離
  • Elmの影響:
    • Evan Czaplickiによって作られた純粋関数型言語
    • "Model-View-Update"アーキテクチャを成文化
    • Dan AbramovがReduxを作成した時、Elmからインスピレーションを得たと明言
    • Reduxのreducerは直接Elmのupdate関数をモデル化: (state, action) => newState
  • React Hooksへの移行: ステートフルなクラスを関数合成に置き換え、エコシステムはFPに決定的にシフト
  • 収束: ライブラリパターン、Elmの厳格性、Reactの進化を通じて、Haskell由来の純粋性に関するアイデアが主流のJavaScript実践となった

■ 6. CSS-in-JS: グローバルスコープへの戦争

  • CSSの設計: グローバルであるように設計された。スタイルはカスケード、継承し、境界を越えて合成する。これにより小さなスタイルシートが巨大なドキュメントを制御でき、チームがアプリケーション間でデザインシステムを共有できる
  • 関数型プログラマーの視点: グローバルスコープは危険。暗黙の依存関係と予測不可能な結果を生む
  • CSS-in-JSの登場: styled-components、Emotion、JSS
    • 約束: コンポーネントの分離
    • スタイルはコンポーネントにスコープされ、カスケードの驚きなし、命名の衝突なし
    • スタイルはデータになり、JavaScriptを通じて渡され、予測可能に要素にバインドされる
  • コスト:
    • 実行時にスタイルを生成し、コンポーネントがマウントされる時に<style>タグに注入
    • クリティカルレンダリングパスにJavaScript実行を追加
    • サーバーサイドレンダリングが複雑に: レンダリング中にスタイルを抽出し、シリアライズし、クライアントでリハイドレートする必要
    • デバッグは.css-1xbq8d9のような実行時生成クラス名を伴う
    • カスケードを失う: まさにCSSを強力にしていた機能
  • さらに悪いこと: ブラウザ最適化された宣言的言語をJavaScript(シングルスレッドランタイム)に移動。ブラウザはCSSを並列で、メインスレッド外で解析・適用できる。styled-componentsバンドルはメインスレッドの作業で、インタラクティビティをブロックする
  • プラットフォームの解決策: Webには解決策があった。スタイルシートと呼ばれるもの。しかし十分に純粋ではなかった

■ 7. Tailwind CSSへのピボット

  • 問題認識後の転換: 実行時CSS生成の代わりにユーティリティクラスを使用。styled-componentsの代わりにJSX内でクラスを合成
  • 改善点: 少なくともコンパイル時で実行時ではない。スタイルを注入するためにメインスレッドをブロックしない。ハイドレーション複雑性なし
  • しかしカスケードとの戦いは継続:
    • .button { padding: 1rem; }を一度書いてすべてのボタンにカスケードさせる代わりに
    • class="px-4 py-2 bg-blue-500"をすべての単一ボタン要素に書く
    • 実行時オーバーヘッドを別の問題セットと交換: マークアップ内のクラススープ、巨大なHTMLペイロード、一箇所で全体的なデザイン変更を行うカスケードの能力の喪失
  • ネストセレクタへの反発:
    • Tailwindが&を使用したネストセレクタのサポートを追加(開発者がよりカスケード的なスタイルを書けるようにする機能)
    • David Khourshid(XStateの作成者)がTailwindでネストセレクタを使う例を共有
    • 即座の反発: これはTailwindの目的を台無しにする、伝統的なCSSの「問題」を持ち込む、ユーティリティファーストの哲学に違反する
  • 意味すること:
    • プラットフォームにはカスケードがある
    • CSS-in-JSはそれを排除しようとして失敗
    • Tailwindはユーティリティでそれを回避しようとした
    • Tailwindが慎重にカスケード的機能を再導入すると、何年ものアンチカスケードイデオロギーで訓練された開発者がそれを拒否
    • カスケードが危険だと教えることに長い時間を費やしたため、自分たちのツールがプラットフォーム機能を再導入しようとしても、彼らはそれを望まない
  • 結論: もはやプラットフォームに無知なだけではない。イデオロギー的に反対している

■ 8. 合成イベント: プラットフォームの抽象化

  • Reactの合成イベント: ブラウザの不整合を正規化し、イベントをレンダリングライフサイクルに統合
    • DOMノードに直接リスナーをアタッチする代わりに、イベント委任を使用
    • ルートでリッスンし、自身のシステムを通じてハンドラーにイベントをルーティング
  • FP視点からのエレガンス: イベントはコンポーネントツリーを流れるデータになる。DOMに直接触れない。すべてがReactの制御された宇宙内に留まる
  • しかしネイティブブラウザイベントは既に動作する: バブル、キャプチャ、十分に仕様化されている。ブラウザは何十年もイベントディスパッチを最適化してきた
  • 合成レイヤーによる追加:
    • イベントオブジェクトのメモリオーバーヘッド
    • すべてのインタラクションの変換ロジック
    • ネイティブAPIと異なる動作をする時のデバッグ摩擦
  • さらに悪いこと: プラットフォームを避けるように開発者を訓練。開発者はReactのイベントシステムを学び、Webのものを学ばない。サードパーティライブラリやカスタム要素と作業する必要がある時、インピーダンスミスマッチに遭遇。addEventListenerが自分のコードベースで外国のAPIになる
  • 再び: Webにはこれがあった。ブラウザのイベントシステムは高速で、柔軟で、よく理解されている。しかし閉じたシステムのFP理想には十分に制御されていなかった

■ 9. クライアントサイドレンダリングとハイドレーション

  • 論理的極限: 「状態の純粋関数としてのUI」の論理的極限はクライアントサイドレンダリング
    • サーバーは空のHTMLシェルを送信
    • JavaScriptが起動
    • アプリはブラウザで完全にレンダリング
    • FP視点: クリーン。アプリは初期状態を取りDOMツリーを生成する決定論的関数
  • Web視点: 災害
    • JavaScriptが解析・実行し、手動でDOMを構築する間、ブラウザは待機
    • ユーザーは空白画面を見る
    • スクリーンリーダーは空のドキュメントを得る
    • 検索エンジンは何も見ない
    • プログレッシブレンダリング(ブラウザの最も強力な機能の1つ)が未使用

■ 10. サーバーサイドレンダリングとハイドレーションの矛盾

  • SSRの復活: 業界は気づいた。しかしメンタルモデルはまだ「JavaScriptがDOMを所有」
  • ハイドレーション:
    • サーバーがHTMLをレンダリング
    • クライアントがJavaScriptで同じツリーをレンダリング
    • Reactが両方を歩いてイベントハンドラーをアタッチ
    • ハイドレーション中、ページは可視だが不活性
    • クリックは何もしない、フォームは送信しない
  • アーキテクチャ的に不条理:
    • ブラウザは既にページをレンダリング済み
    • 既にクリック処理方法を知っている
    • しかしフレームワークが合成イベントシステムを通じてすべてのインタラクションを所有したいため、何かが動作する前にJavaScriptで全体のコンポーネントツリーを再作成する必要
  • インフラへの拡張:
    • すべてのユーザーが2倍のリクエスト数を行う
    • サーバーがページをレンダリングしデータを取得
    • クライアントが起動し、ハイドレーションのためにコンポーネントツリーを再構築するために全く同じデータを再度取得
    • なぜ? フレームワークが生成したHTMLを信頼できないから
    • イベントハンドラーをアタッチし状態を管理するために、JavaScriptでUIの内部表現を再構築する必要
  • 無駄で高コスト:
    • データベースクエリが2回実行
    • API呼び出しが2回実行
    • キャッシュレイヤーが2回ヒット
    • CDNコストが2倍
    • なぜ? フレームワークがすべての状態がJavaScriptに存在する純粋関数モデルを維持できるように
  • 結論: ハイドレーションは、Webを能力を持つプラットフォームではなく白紙のキャンバスとして扱う時に起こること。WebはストリーミングHTML、プログレッシブエンハンスメント、即座のインタラクティビティを与えた。JSON、JavaScriptバンドル、重複ネットワークリクエスト、「現実を再構築する間お待ちください」に置き換えた

■ 11. モーダル問題: ベストプラクティスとして誤った実践を教える

  • ネイティブ<dialog>要素:
    • フォーカストラッピングを管理
    • Escapeキー却下を処理
    • バックドロップを提供
    • ボディのスクロールロックを制御
    • アクセシビリティツリーと統合
    • DOM内に存在するが開かれるまで隠れたまま
    • JavaScriptマウント不要
    • 高速、アクセシブル、ブラウザベンダーによって実戦テスト済み
  • チュートリアル・ブートキャンプで教えられること:
    • <div>要素でモーダルを構築
    • isOpenがtrueの時に条件付きレンダリング
    • 手動でクリックアウトサイドハンドラーをアタッチ
    • Escapeキーをリッスンするエフェクトを書く
    • フォーカストラッピング用の別のエフェクトを追加
    • 独自のスクロールロックロジックを実装
    • ARIA属性追加を忘れずに
    • イベントリスナーのクリーンアップを忘れずに、さもなくばメモリリーク
  • 結果: ブラウザが無料で提供するものを粗末に再作成するために100行以上のJavaScriptを書いた
  • 訓練の問題:
    • 開発者はネイティブソリューションを探すことさえしないように訓練される
    • プラットフォームが見えなくなる
    • 「モーダルの作り方は?」への答えは「ライブラリをインストール」や「これが私のカスタムフック」であり、決して「<dialog>を使え」ではない
  • 教育が問題:
    • 影響力のあるチュートリアル作者やブートキャンプカリキュラムがネイティブAPIをスキップしてReactパターンを支持する時
    • 代替アプローチを示しているだけでなく、積極的に誤った実践を教えている
    • 世代の開発者がアクセシブルでない<div>スープを構築することを学ぶ
    • それがフレームワークの反応性モデルに適合するから
    • プラットフォームが既にこれらの問題を解決していたことを決して知らない
  • ブートキャンプだけではない: 最も人気のあるコンポーネントライブラリも同じ選択
    • shadcn/uiはDialogコンポーネントをRadix UIプリミティブ上に構築
    • ネイティブ<dialog>要素の代わりに<div role="dialog">を使用
    • ネイティブ<dialog>サポートを要求するオープンなGitHub issueがある
    • しかし暗黙のメッセージは明確: ブラウザと協働するよりも再実装する方が簡単

■ 12. フレームワークがプラットフォームの進化についていけない時

  • より深い問題: 無知や惰性以上のもの。フレームワーク自体がプラットフォームの進化と協働することに苦労している。プラットフォーム機能が悪いからではなく、フレームワークのアーキテクチャ的前提がそれらに対応できないから
  • Radix UIが<div role="dialog">を選ぶ理由:
    • ネイティブ<dialog>要素は自身の状態を管理: いつ開いているか知っている、自身の可視性を処理、内部でフォーカスを制御
    • Reactの反応性モデルはすべての状態がJavaScriptに存在し、DOMに一方向に流れることを期待
    • ネイティブ要素が自身の状態を管理すると、Reactのメンタルモデルが崩壊
    • React状態のisOpen<dialog>要素の実際の開閉状態を同期させるのは、refs、エフェクト、命令的呼び出しの悪夢
    • まさにReactが排除するはずだったもの
    • パターンをステートフルなネイティブ要素と協働するように適応させるよりも、フレームワークに適合する方法で全体の動作をJavaScriptで再実装する方がアーキテクチャ的に簡単
  • 新しいプラットフォーム機能の例:
    • アコーディオン? Webには<details><summary>
    • ツールチップ? title属性と新興のpopover API
    • 日付ピッカー? <input type="date">
    • カスタムドロップダウン? Webは今<select>要素をappearance: base-select::picker(select)疑似要素でスタイリングサポート
    • <option>要素内に画像付き<span>要素も入れられる
    • デザイナーがカスタムスタイリングを望んだという理由だけで存在する無数のJavaScript selectライブラリの必要性を排除
  • フレームワークの問題:
    • 条件付きレンダリングとコンポーネント状態を奨励するため、これらの要素はJavaScriptが存在すべきと決めるまでレンダリングされない
    • メンタルモデルは「状態が変わった時にUIが現れる」であり、「UIは存在し、状態が可視性を制御する」ではない
    • プラットフォームが何年もJavaScriptで再構築されてきた正確な機能を追加しても、エコシステムの勢いは多くの開発者がこれらの機能の存在を決して学ばないことを意味
  • 真に不条理な部分:
    • 開発者がこれらの新しいプラットフォーム機能を知っていても、フレームワーク自体がそれらを処理できない
    • MDNのカスタマイズ可能な<select>要素のドキュメントに警告:「一部のJavaScriptフレームワークはこれらの機能をブロック; 他では、サーバーサイドレンダリング(SSR)が有効な時にハイドレーション失敗を引き起こす」
    • プラットフォームは進化した
    • HTMLパーサーは今<option>要素内により豊かなコンテンツを許可
    • しかしReactのJSXパーサーとハイドレーションシステムはこれのために設計されていない
    • <option>はテキストのみを含むと期待
    • プラットフォームの進化に対応するためにフレームワークを更新するには時間、調整、チームが躊躇する破壊的変更が必要
  • 結論: Webプラットフォームは全カテゴリのJavaScriptライブラリを排除する機能を追加したが、支配的なフレームワークはハイドレーションエラーを引き起こさずにそれらの機能を使用できない。開発を容易にするはずだったスタックが、今や構築されているプラットフォームに遅れている

■ 13. ルーティングとフォーム: JavaScriptオールザウェイダウン

  • ブラウザのネイティブ機能:
    • ルーティング: <a>タグ、History API、前後ボタン
    • フォーム: <form>要素、検証属性、送信イベント
    • JavaScriptなしで動作
    • デフォルトでアクセシブル
    • 高速
  • 現代フレームワークの対応:
    • React Router、Next.jsのルーター、Vue Router
    • リンククリックをインターセプト
    • ブラウザナビゲーションを防止
    • JavaScriptでルーティングを処理
    • なぜ? クライアントサイドルーティングは純粋な状態遷移のように感じる: URL変更、状態更新、コンポーネント再レンダリング、ページリロードなし、JavaScript状態の「喪失」なし
  • 失ったもの:
    • ナビゲーションがJavaScriptに依存
    • Ctrl+クリックで新しいタブで開く? 慎重に再実装しない限り壊れる
    • 右クリックでリンクをコピー? URLがレンダリングされたものと一致しない可能性
    • 標準ナビゲーションパターンに依存するアクセシビリティツール? 混乱
  • フォームも同じ扱い:
    • ブラウザに送信、検証、アクセシビリティを処理させる代わりに、フレームワークはJavaScript制御フォームを奨励
    • Formik、React Hook Form、非制御vs制御入力
    • <form>が既に行うことを管理するためだけに存在する全ライブラリ
    • ブラウザは<input type="email">をJavaScriptなしで即座に検証できる
    • しかし十分に反応的ではないため、JavaScriptで検証を再構築し、クライアントに出荷し、ロジックが正しいことを願う
  • 再び: Webにはこれらのプリミティブがあった。「状態はJavaScriptを通じて流れる」というFPに触発されたメンタルモデルに適合しなかったため拒否した

■ 14. 失ったもの

  • プログレッシブエンハンスメント:
    • かつてのベストプラクティス: 動作するHTMLから始め、スタイルのためにCSSを重ね、インタラクティビティのためにJavaScriptを追加。ページはすべてのレベルで動作
    • 今: JavaScriptから始めて後方に作業し、コンポーネントツリーからHTMLを絞り出そうとし、ハイドレーションが壊れないことを願う
  • 組み込みアクセシビリティ:
    • ネイティブHTML要素はデフォルトでロール、ラベル、キーボードサポート
    • カスタムJavaScriptウィジェットはaria-*属性、フォーカス管理、キーボードハンドラーが必要
    • すべて忘れやすいか設定ミスしやすい
  • パフォーマンス:
    • ブラウザのストリーミングパーサーは到着するHTMLをレンダリングできる
    • 現代フレームワークはJavaScriptを送信、JavaScriptを解析、JavaScriptを実行、そしてやっとレンダリング。それは遅い
    • ブラウザはCSSとHTMLを積極的にキャッシュできる
    • JavaScriptバンドルはすべてのデプロイで無効化
  • シンプルさ:
    • <a href="/about">は8文字
    • クライアントサイドルーターは依存関係、設定ファイル、メンタルモデル
    • <form action="/submit" method="POST">は自己文書化
    • 検証付き制御フォームは数十行の状態管理
  • プラットフォームとの整合性:
    • ブラウザベンダーはHTML解析、CSSレンダリング、イベントディスパッチの最適化に何百万も費やす
    • 開発者はそれらの機能をJavaScriptで再構築するのに何千時間も費やす、より遅く

■ 15. なぜこうなったか

  • 無能の話ではない: 賢い人々が本当の理由でこれらのツールを構築
  • 2010年代初頭の状況:
    • JavaScriptアプリケーションが保守不可能に
    • jQueryスパゲッティがコードベース全体に広がる
    • 双方向データバインディングがデバッグ不可能なカスケード更新を引き起こす(皮肉なことに、Backboneのドキュメントは双方向バインディングに対して明示的に助言し、「実際のアプリでは特に有用ではない傾向」と述べたが、多くの開発者がプラグインを通じて実装)
    • コミュニティは規律を望み、FPがそれを提供: UIを状態の純粋関数として扱う、データを一方向に流す、共有可変状態を排除
  • Reactの到着(2013):
    • これらの理想を結晶化
    • UI = f(state)の世界を約束: データを与え、コンポーネントツリーを返し、データが変わったら再レンダリング
    • 手動DOM操作なし
    • 暗黙の副作用なし
    • ただ純粋で予測可能な変換
  • 魅力的で多くの点で機能した: しかし、JavaScriptをWebのイメージで作るのではなく、WebをJavaScriptのイメージで再構築する道に進んだ
  • 複雑なアプリケーションでの正当性:
    • 何百もの対話型コンポーネントを持つダッシュボード
    • リアルタイムコラボレーションツール
    • データ可視化プラットフォーム
    • Reactのモデルは手動でイベントハンドラーを配線し変更を追跡するよりも genuinely better
  • FP純粋主義者の誤り:
    • 予測不可能な変更がバグを引き起こすことは正しかった
    • 解決策がプラットフォームの変更に優しいAPIを避けることではなく、それらをうまく使うことを学ぶことだったという点で間違っていた
    • しかし2013年の混沌では、その区別は重要でなかった
    • Reactは機能し、スケールし、Facebookが本番環境で使用していた
  • ハイプサイクル:
    • Reactが会話を支配
    • すべてのカンファレンスでReactトーク
    • すべてのチュートリアルがReactを出発点として仮定
    • CSS-in-JSが「モダン」に
    • クライアントサイドレンダリングがデフォルトに
    • Facebook、Airbnb、Netflixなどの大企業がこれらのパターンを採用すると、業界標準に
    • ブートキャンプがReactのみを教える
    • 求人がReact経験を要求
    • ナラティブが固まる: これが今Webを構築する方法
  • 自己強化エコシステム:
    • Reactが採用パイプラインとStack Overflow回答を支配すると、代替案は苦戦
    • 既にReactに投資したチーム(開発者訓練、コンポーネントライブラリ構築、パターン確立)は莫大なスイッチングコストに直面
    • 新しい開発者は仕事が要求するからReactを学ぶ
    • 仕事は開発者が知っているからReactを要求
    • サイクルは、Reactが特定の仕事に最適なツールかどうかとは無関係に、自己を養う
  • 道を見失った場所:
    • 「Reactが複雑なアプリケーション問題を解決」から「Reactがウェブサイトの構築方法」への移行のどこかで
    • 解決している問題が実際にこれらのソリューションを必要とするかどうかを問うのをやめた
    • Next.jsで個人ブログを構築する開発者を見た(95%静的コンテンツで多分お問い合わせフォームだけ、ブートキャンプで学んだから)
    • ゼロインタラクティビティのマーケティングサイトにReactを選ぶ企業を見た、適切だからではなく、他に何も知らない開発者を雇えないから
  • 根本的な変化:
    • 複雑でステートフルなアプリケーション用に設計されたツールが、1995年にHTMLとCSSでWebが解決した問題を含むすべてのデフォルトに
    • 世代の開発者がほとんどのウェブサイトはフレームワークをまったく必要としないことを決して学ばなかった
    • 質問は「この問題はReactが必要か?」ではなく「どのReactパターンを使うべきか?」になった
    • プログレッシブレンダリング、セマンティックHTML、カスケード、即座のナビゲーションなどのプラットフォームのネイティブ機能は今「古臭い」と見なされる
    • それらをJavaScriptで再発明することが「ベストプラクティス」に
  • 結論: 決して設計されていないプラットフォームで関数型純粋性を追求。ミスマッチを覆うために複雑さを構築

■ 16. 進むべき道

  • 良いニュース: 学んでいる。業界はプラットフォームを再発見している
  • 新しいアプローチ:
    • HTMX: HTMLを交換媒体として受け入れる。サーバーがHTMLを送信、ブラウザがレンダリング、ハイドレーション不要
    • Qwik: 再開可能アーキテクチャでハイドレーションを完全に回避、必要なものだけをシリアライズ
    • Astro: 最小限のJavaScriptでサーバーレンダリングHTMLをデフォルト
    • RemixとSvelteKit: Web標準に寄りかかる: JSなしで動作するフォーム、プログレッシブエンハンスメント、ブラウザのキャッシュ活用
  • これらのツールが認めること: Webは強力なネイティブ機能を持つドキュメントベースのプラットフォーム。戦うのではなく、協働する
  • 意味しないこと: コンポーネントや反応性を放棄することではない
  • 意味すること:

    • UI = f(state)がフレームワーク内で有用なモデルであることを認識、ブラウザスタック全体を再構築する正当化ではない
    • スタイリングにCSS、インタラクションにネイティブイベント、構造にHTMLを使用
    • そしてプラットフォームが提供する以上のインタラクティビティが必要な時にJavaScriptに手を伸ばす
  • 次の10年の最高のフレームワーク: それにもかかわらずではなく、Webのように感じるもの

■ 17. 結論

  • 追求の結果: 関数型純粋性を追求する中で、より複雑で、より壊れやすく、実行されるプラットフォームとの整合性が低いフロントエンドスタックを構築した
  • 再作成したもの:
    • JavaScriptでのCSS
    • 合成ラッパーでのイベント
    • ハイドレーションレイヤーでのレンダリング
    • クライアントサイド状態マシンでのルーティング
  • 理由: 予測可能性、制御、クリーンな抽象化を望んだから
  • Webの本質:
    • 決して純粋であることを意図されていなかった
    • 何十年もの創発的行動、実用的妥協、急進的オープン性の上に構築された広大で乱雑で奇跡的なプラットフォーム
    • その可変性はバグではない。1995年に書かれたドキュメントが2025年にまだレンダリングされる理由
    • そのグローバルスコープは危険ではない。何十億ものページがデザイン言語を共有できる理由
  • 最終的な問い: おそらくWebは純化される必要はなかった。おそらくただ理解される必要があっただけ