定義
SSR をストリーミングに変えれば Lighthouse スコアが上がるだろうと期待するとき、実際に何が良くなり何はそのままなのかを切り分ける文書だ。Streaming SSR(ストリーミングサーバーレンダリング)は、サーバーが全ツリーを準備し終えて(await して)HTML を一度に送るのではなく、shell(先に送る骨組みの HTML)と Suspense 境界(データを待つ間は代替 UI を見せ、準備できたら埋める React 境界)を**チャンク(かけら)単位で flush(送り出す)**方式だ(Next.js App Router の streaming RSC など、RSC=React Server Component)。Lighthouse(Google のパフォーマンス測定ツール)・lab CWV(実験室環境で測った Core Web Vitals)の利得は、ストリーミング自体よりも LCP 候補(最も大きいコンテンツ要素)がどのチャンクにあるかで決まる。
なぜ必要か
ssr-prefetch-query-cache-hydration は、クライアントで session → api/data の順に連鎖リクエストが続く waterfall(前のリクエストが終わってから後のリクエストが始まる滝状の遅延)を減らす。Streaming は別の軸だ — サーバーが HTML バイトをいつ送り出し始めるか。両者を混同すると「streaming さえ入れれば Lighthouse が上がる」という誤った優先順位が生まれる。auth-gated ホーム(ログインの有無で内容が分かれるホーム)のように LCP が API 結果に縛られたページでは、LCP に必要なデータを後の Suspense に先送りすると FCP(First Contentful Paint、最初のピクセルが描画される時点)だけが良くなり、LCP はそのままか CLS(Cumulative Layout Shift、後からコンテンツが埋まって画面が押される度合い)が悪化することがある。
動作原理
| パターン | 最初のバイト / shell | LCP 要素 |
|---|---|---|
| Blocking SSR(全体 await) | 遅い(TTFB↑) | データ準備後に一度に paint |
| Stream, LCP late | shell 先 | LCP は後のチャンク — FCP↑、LCP≈ |
| Stream, LCP early | shell + LCP データ | secondary だけ defer — FCP↑、LCP↑ 可能 |
Lighthouse Performance は LCP・TBT・CLS・FCP・SI などを加重合成した lab スコアだ(lighthouse-measurement-accuracy)。shell だけ速く出ても FCP / Speed Index は上がりうるが、LCP ms は動かないことがある。スコアだけを見て「良くなった」と断定してはいけない。
Prefetch との関係:
- Prefetch + hydrate — ブラウザ内の waterfall を除去。
- Streaming — 同じサーバー待ちを待ちながらも CSS/JS のパース・shell paint を重ねる余地。
- Prefetch がすでに LCP 経路の核心なら、streaming の追加の利得はたいてい付加データの defer 側だ。
実務適用
- LCP-critical は前のチャンク — auth + LCP に必要なメタ(最初の画像 URL など)は blocking prefetch または最初のストリームに置く(carousel-viewport-image-deferral)。
- secondary だけ Suspense — below-fold のウィジェット、付加クエリ、非 LCP パネルを stream defer。
- skeleton セット — 後のチャンクが付くときに高さ・行数を予約しないと CLS が起きる(cls-skeleton-layout-reservation)。
- 測定 — Lighthouse スコアと trace LCP ms を分離し、production
build && startで N 回の median により before/after(lab-performance-measurement-variance)。
トレードオフ
| 選択 | 利得 | コスト |
|---|---|---|
| Blocking + LCP prefetch | LCP 経路がシンプル・予測可能 | TTFB・最初の paint 遅延 |
| Stream, LCP early | FCP/SI + LCP を同時に改善可能 | 境界設計・チャンク順序の複雑度 |
| Stream, LCP late | shell・FCP の体感 | LCP 無利得・CLS リスク |
| Prefetch のみ(stream なし) | client waterfall を除去 | shell flush の利得なし |
使ってはいけない場合
- 公開静的ページ — CDN/SSG だけで十分な場合。
- LCP 要素を「後で埋まる場所」としてだけ置き、stream の利得を LCP SLA に期待する場合。
- skeleton・レイアウト予約なしに大きなブロックを後のチャンクに入れる場合。
よくある間違い
- Streaming 導入 = Lighthouse Performance の自動上昇と仮定する。
- LCP-critical API を後の Suspense に先送りし、FCP だけが改善したのを成功として記録する。
- Prefetch と streaming を同じ最適化として扱い、優先順位を入れ替える。
- スコアだけを見て LCP ms・CLS を再測定しない。
関連概念
- ssr-prefetch-query-cache-hydration — client waterfall vs HTML flush の軸
- largest-contentful-paint — LCP 候補・改善
- lighthouse-measurement-accuracy — スコア vs trace ms
- cls-skeleton-layout-reservation — stream チャンク + skeleton
- carousel-viewport-image-deferral — LCP メタだけ early、バイトは defer
- lab-performance-measurement-variance — N 回の median 比較