react-selective-hydration について
React 18 の SSR 開発者向けに、選択的ハイドレーションを解説します。ストリーミングと Suspense を使い、すべてのコンポーネントを待たずに準備済みの部分を操作可能にします。
主な機能
- 01Suspense によるハイドレーション領域の分割
- 02全コンポーネントの準備前に HTML をストリーミング
- 03遅いコンポーネントによる兄弟要素のブロック防止
- 04クライアント到着後のコンポーネントのハイドレーション
活用シーン
- 01SSR ページの一部を早く操作可能にする
- 02データ取得コンポーネントによる水合の遅延防止
- 03大型コンポーネントの読み込み中に重要領域を利用可能に保つ
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ patternsdev/ skills --skill react-selective-hydrationインストール後、Claude Code で/react-selective-hydrationを入力して読み込まれたか確認します。
詳細
選択的ハイドレーション
これまでの記事では、ハイドレーションを伴う SSR がユーザーエクスペリエンスをどのように向上させるかを説明しました。React は、react-dom/server ライブラリが提供する renderToString メソッドを使って、サーバー上でツリーを(すばやく)生成できます。生成されたツリー全体がクライアントに送信されます。レンダリングされた HTML は、JavaScript バンドルが取得されて読み込まれるまでインタラクティブではありません。その後、React がツリーをたどってハイドレーションを行い、ハンドラーをアタッチします。
ただし、現在の実装にはいくつかの制約があるため、この方法ではパフォーマンス上の問題が発生することがあります。
使用する場面
- すべての JavaScript が読み込まれる前に、SSR ページの一部をインタラクティブにしたい場合に使用します
- 遅いコンポーネント(データ取得を行うコンポーネントなど)がページ全体のハイドレーションを妨げている場合に役立ちます
手順
Suspense境界を使って、独立してハイドレーション可能な UI のチャンクを区切ります- ストリーミング SSR には
renderToPipeableStream(Node)またはrenderToReadableStream(edge)を使用します - 重いデータ取得コンポーネントは
Suspenseの内側に配置し、兄弟コンポーネントのハイドレーションを遅らせないようにします - 重要なインタラクティブコンポーネントが、長時間表示されるローディングフォールバックの内側に配置されないようにします
- 選択的ハイドレーションのメリットを得るには、
hydrateRoot(React 18 以降)を使用します
詳細
サーバーでレンダリングされた HTML ツリーをクライアントに送信できるようになる前に、すべてのコンポーネントの準備が整っている必要があります。つまり、外部 API 呼び出しや遅延の原因となる処理に依存するコンポーネントがあると、小さなコンポーネントのレンダリングまで遅れることがあります。
ツリーの生成が遅くなることに加えて、React がツリーを一度しかハイドレーションしないという問題もあります。つまり、React がいずれかのコンポーネントをハイドレーションできるようになるには、まずすべてのコンポーネントの JavaScript を取得する必要があります。そのため、バンドルサイズの小さいコンポーネントも、サイズの大きなコンポーネントのコードが取得されて読み込まれるまで待たなければならず、React がウェブサイト上のコンポーネントをハイドレーションできるようになるまで時間がかかります。この間、ウェブサイトは操作できない状態のままです。
React 18 では、ストリーミングによるサーバーサイドレンダリングと、新しいハイドレーションの方法である選択的ハイドレーションを組み合わせることで、これらの問題を解決します。
renderToString の代わりに、最新の React SSR では Node ランタイムで renderToPipeableStream() を、Web Stream ランタイムで renderToReadableStream() を使用します。
これらの API を hydrateRoot() および Suspense と組み合わせると、サイズの大きなコンポーネントの準備が整うのを待たずに HTML のストリーミングを開始できます。つまり、SSR を使用する際にコンポーネントを遅延読み込みしても、ページの残りの部分のハイドレーションを妨げずに済みます。
以前はツリーの生成と TTI を遅らせていた Comments コンポーネントは、Suspense でラップされています。これにより、React はこのコンポーネントによってツリーの残りの部分の生成が遅れないようにします。代わりに、React はフォールバックコンポーネントを最初にレンダリングする HTML として挿入し、クライアントに送信する前にツリーの残りの部分の生成を続けます。
その間、Comments コンポーネントに必要な外部データの取得は続けています。
選択的ハイドレーションを使えば、Comments コンポーネントが送信される前でも、クライアントに送信済みのコンポーネントをハイドレーションできます。
Comments コンポーネントのデータの準備が整うと、React はこのコンポーネントの HTML と、フォールバックのローダーを置き換える小さな <script> のストリーミングを開始します。
新しい HTML が挿入された後、React はハイドレーションを開始します。
React 18 では、SSR を使う際によく発生していたいくつかの問題が解決されています。
ストリーミングレンダリングでは、サーバーでの生成に時間がかかるコンポーネントによって FCP や TTI が遅くなるリスクを避けながら、準備が整ったコンポーネントから順次ストリーミングを開始できます。
すべての JavaScript の読み込みを待たずにハイドレーションを開始でき、すべてのコンポーネントがハイドレーションされる前からアプリを操作できるため、コンポーネントはクライアントにストリーミングされるとすぐにハイドレーションできます。