CMSの編集モード機能を維持しながら、ドキュメントサイトが高速な静的ページ読み込みを実現する方法を説明します
このガイドでは、ドキュメントサイトがCMSの編集モード機能を維持しつつ、高速な静的ページ読み込みを実現する方法を説明します。
同一コンテンツに対して2つのルートを使用しています:
app/
├── [...slug]/page.tsx # 本番: force-static(高速)
└── preview/[...slug]/page.tsx # 編集モード: force-dynamic(searchParamsを読み取る)
プロキシミドルウェアが編集モードのリクエストを透過的にリライトします:
ユーザーリクエスト: /en/headless/quickstart?edit_mode=true
↓
プロキシが ?edit_mode=true を検知
↓
内部的に /preview/en/headless/quickstart?edit_mode=true へリライト
↓
動的ルートが編集用ラッパー付きでレンダリング
ユーザーがURLで /preview を目にすることは決してありません — これは内部リライトです。
// app/[...slug]/page.tsx
export const dynamic = 'force-static';
export const revalidate = 60;
export default async function Page({ params }) {
// searchParams なし - ページは完全な静的生成
return
// app/preview/[...slug]/page.tsx
export const dynamic = 'force-dynamic';
export default async function PreviewPage({ params, searchParams }) {
// searchParams が利用可能 - edit_mode を検知できる
return <ParametricRoutePage params={params}
?edit_mode=true を読み取ることができます// src/proxy.ts
export const proxy = async (request: NextRequest) => {
const { pathname, searchParams } = request.nextUrl;
const editMode = searchParams.get('edit_mode');
| シナリオ | レスポンスタイム | レンダリング |
|---|---|---|
| 本番ページ(キャッシュ済み) | 約50〜100ms | CDNからの静的配信 |
| 本番ページ(キャッシュ陳腐化) | 約50〜100ms + バックグラウンド更新 | 静的配信後にISR |
| 編集モード | 約500〜1500ms | 動的SSR |
revalidate = 60 の設定はISRを有効化します。これはページが60秒ごとに再計算されるという意味ではありません。
ISRは stale-while-revalidate(期限切れでも即時提供しつつ裏で更新) パターンを利用します:
リクエストが来る:
→ キャッシュページが60秒未満? → キャッシュから提供(即時)
→ キャッシュページが60秒超過? → 期限切れキャッシュを提供(即時)
+ 次回リクエスト向けにバックグラウンドで再検証
リクエストがなければ = 再計算は一切起こりません。
例:
60秒のウィンドウは安全策です。理想的には、CMSコンテンツが更新された際にWebhook経由でオンデマンド再検証を利用します。
| ユースケース | URL | 使用ルート |
|---|---|---|
| 通常閲覧 | /en/headless/quickstart | 静的 |
| CMSテンプレートビルダー | /en/headless/quickstart?edit_mode=true | プレビュー(リライト経由) |
| AIブロックプレビュー | /en/headless/quickstart?ai_preview=1 | プレビュー(リライト経由) |
単純なアプローチ(force-staticなし、プレビュールートなし)でも動作しますが、遅くなります:
// 単純なアプローチ - 動作はするがリクエストごとに約1〜2秒
export default async function Page({ params, searchParams }) {
return <ParametricRoutePage params={params} searchParams={searchParams} />;
}
これはリクエストのたびに動的レンダリングします。ページ数の多いドキュメントサイトでは次のような結果になります:
二重ルートアーキテクチャにより、閲覧者には静的な速度を、編集者には動的な機能を提供するという両立が可能になります。