03. Suspense境界との統合
静的シェルと動的コンテンツを組み合わせて、高速で柔軟なページを構築しましょう。
静的シェル + 動的コンテンツ
ページの静的部分をキャッシュし、動的部分はSuspenseでストリーミング
基本的なパターン
import { Suspense } from "react";
// 静的シェル(キャッシュされる)
async function Header() {
"use cache";
return <header>Static Header</header>;
}
// 動的コンテンツ
async function DynamicContent() {
const data = await fetchRealtimeData();
return <div>{data}</div>;
}
export default async function Page() {
return (
<div>
<Header /> {/* 即座に表示 */}
<Suspense fallback={<Loading />}>
<DynamicContent /> {/* ストリーミング */}
</Suspense>
</div>
);
}実際の動作デモ:
静的シェル(即座に表示)
HIT12:10:47
Next Lift Dashboard
あなたのトレーニング管理システム
- キャッシュ時刻
動的コンテンツ(ストリーミング)
💡 ページをリロードすると、静的シェルは即座に表示され、動的コンテンツは1秒後にストリーミングで表示されます。
このパターンのメリット
- • 初回表示が高速: 静的部分はキャッシュから即座に表示
- • 段階的レンダリング: 準備できた部分から順次表示
- • 柔軟性: 静的と動的のバランスを自由に調整
- • SEO対策: 重要なコンテンツは静的にプリレンダリング
ネストしたSuspense境界
複数のSuspenseを組み合わせて、きめ細かい制御を実現
ネストしたSuspense
// ネストしたSuspense境界
export default function Page() {
return (
<div>
<StaticHeader />
<Suspense fallback={<HeaderSkeleton />}>
<DynamicHeader />
<div className="grid grid-cols-2">
<Suspense fallback={<CardSkeleton />}>
<StatsCard />
</Suspense>
<Suspense fallback={<CardSkeleton />}>
<ActivityCard />
</Suspense>
</div>
</Suspense>
</div>
);
}使用ケース
- • ダッシュボード: 各ウィジェットを独立してストリーミング
- • 商品ページ: 商品情報、レビュー、関連商品を別々に表示
- • 記事ページ: 本文、コメント、推奨記事を段階的にロード
⚠️ 注意点
- • Suspense境界を細かくしすぎると管理が複雑に
- • スケルトンUIは実際のコンテンツサイズに近づける
- • ネストが深すぎるとパフォーマンスに影響
ハイブリッドキャッシング
キャッシュされたコンポーネント内に動的コンテンツを配置
ハイブリッドパターン
// ハイブリッドパターン
async function OptimizedPage() {
"use cache";
cacheLife("hours");
const staticData = await getStaticData();
return (
<Layout data={staticData}> {/* キャッシュされた部分 */}
<Suspense fallback={<Skeleton />}>
<DynamicWidget /> {/* 動的な部分 */}
</Suspense>
</Layout>
);
}ハイブリッドパターンの特徴
「use cache」でマークされたコンポーネント内に、Suspenseで囲まれた動的コンテンツを配置できます。 これにより、レイアウトやナビゲーションなどの静的部分をキャッシュしながら、 コンテンツの一部を動的に保つことができます。
✅ ベストプラクティス
- • レイアウトやナビゲーションは「use cache」でキャッシュ
- • ユーザー固有のデータはSuspenseで動的に取得
- • スケルトンUIで優れたUXを提供
- • cacheLife()で適切な再検証タイミングを設定
フェーズ1完了おめでとうございます!
基礎機能(優先度A)をマスターしました。次は実用的な機能(優先度B)に進みましょう。 cacheTag()による再検証、プライベートキャッシュ、connection() APIなど、実際のアプリケーション開発で役立つ機能を学びます。