ドラフトモード
ドラフトモードを使用すると、Next.jsアプリケーション内のヘッドレスCMSからドラフトコンテンツをプレビューできます。これは、ビルド時に生成される静的ページに便利で、サイト全体を再ビルドすることなく、動的レンダリングに切り替えてドラフトの変更を確認できます。
このページでは、ドラフトモードの有効化と使用方法を説明します。
ステップ1: ルートハンドラの作成
ルートハンドラを作成します。名前は任意で、例えばapp/api/draft/route.ts
などとします。
export async function GET(request: Request) {
return new Response('')
}
次に、draftMode
関数をインポートし、enable()
メソッドを呼び出します。
import { draftMode } from 'next/headers'
export async function GET(request: Request) {
const draft = await draftMode()
draft.enable()
return new Response('ドラフトモードが有効になりました')
}
これにより、ドラフトモードを有効にするためのCookieが設定されます。このCookieを含む後続のリクエストは、ドラフトモードをトリガーし、静的に生成されたページの動作を変更します。
ブラウザの開発者ツールで/api/draft
にアクセスし、Set-Cookie
レスポンスヘッダーに__prerender_bypass
という名前のCookieがあることを確認して、手動でテストできます。
ステップ2:ヘッドレスCMSからルートハンドラにアクセスする
これらの手順は、使用しているヘッドレスCMSがカスタムドラフトURLの設定をサポートしていることを前提としています。サポートしていない場合でも、このメソッドでドラフトURLを保護できますが、ドラフトURLを手動で構築およびアクセスする必要があります。具体的な手順は、使用しているヘッドレスCMSによって異なります。
ヘッドレスCMSからルートハンドラに安全にアクセスするには:
- 任意のトークンジェネレーターを使用して、シークレットトークン文字列を作成します。このシークレットは、Next.jsアプリとヘッドレスCMS間でのみ知られます。
- ヘッドレスCMSがカスタムドラフトURLの設定をサポートする場合、ドラフトURLを指定します(これは、ルートハンドラが
app/api/draft/route.ts
に配置されていることを前提としています)。例:
https://<your-site>/api/draft?secret=<token>&slug=<path>
<your-site>
は、デプロイメントドメインに置き換えてください。<token>
は、生成したシークレットトークンに置き換えてください。<path>
は、表示したいページのパスです。/posts/one
を表示する場合、&slug=/posts/one
を使用します。ヘッドレスCMSによっては、ドラフトURLに変数を含めることができ、
<path>
をCMSのデータに基づいて動的に設定できます:&slug=/posts/{entry.fields.slug}
- ルートハンドラで、シークレットが一致し、
slug
パラメータが存在することを確認し(存在しない場合、リクエストは失敗)、draftMode.enable()
を呼び出してCookieを設定します。次に、ブラウザをslug
で指定されたパスにリダイレクトします:
import { draftMode } from 'next/headers'
import { redirect } from 'next/navigation'
export async function GET(request: Request) {
// クエリ文字列パラメータを解析
const { searchParams } = new URL(request.url)
const secret = searchParams.get('secret')
const slug = searchParams.get('slug')
// シークレットパラメータとnextパラメータを確認
// このシークレットは、このルートハンドラとCMSのみが知っているべきです
if (secret !== 'MY_SECRET_TOKEN' || !slug) {
return new Response('Invalid token', { status: 401 })
}
// ヘッドレスCMSをフェッチして、指定された`slug`が存在するか確認
// getPostBySlugは、ヘッドレスCMSへのフェッチロジックを実装する必要があります
const post = await getPostBySlug(slug)
// slugが存在しない場合、ドラフトモードの有効化を防ぐ
if (!post) {
return new Response('Invalid slug', { status: 401 })
}
// Cookieを設定してドラフトモードを有効化
const draft = await draftMode()
draft.enable()
// フェッチしたポストのパスにリダイレクト
// オープンリダイレクトの脆弱性を避けるため、searchParams.slugにリダイレクトしません
redirect(post.slug)
}
成功すると、ブラウザはドラフトモードCookieと共に表示したいパスにリダイレクトされます。
ステップ3:ドラフトコンテンツのプレビュー
次のステップは、draftMode().isEnabled
の値をチェックするようページを更新することです。
Cookieが設定されているページをリクエストすると、データはリクエスト時(ビルド時ではなく)にフェッチされます。
さらに、isEnabled
の値はtrue
になります。
// データをフェッチするページ
import { draftMode } from 'next/headers'
async function getData() {
const { isEnabled } = await draftMode()
const url = isEnabled
? 'https://draft.example.com'
: 'https://production.example.com'
const res = await fetch(url)
return res.json()
}
export default async function Page() {
const { title, desc } = await getData()
return (
<main>
<h1>{title}</h1>
<p>{desc}</p>
</main>
)
}
ヘッドレスCMSから、または手動でURLを使用してドラフトルートハンドラ(secret
とslug
付き)にアクセスすると、ドラフトコンテンツを表示できるはずです。また、ドラフトを公開せずに更新した場合も、ドラフトを表示できるはずです。