Next.jsでドラフトモードを使用してコンテンツをプレビューする方法
ドラフトモードを使用すると、Next.jsアプリケーションでヘッドレスCMSからのドラフトコンテンツをプレビューできます。これはビルド時に生成される静的ページに役立ちます。動的レンダリングに切り替えることで、サイト全体を再構築することなくドラフトの変更を確認できます。
このページでは、ドラフトモードの有効化と使用方法について説明します。
ステップ1:Route Handlerを作成する
Route Handlerを作成します。例えば、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('Draft mode is enabled')
}
これによりドラフトモードを有効にするクッキーが設定されます。このクッキーを含む後続のリクエストでドラフトモードがトリガーされ、静的に生成されたページの動作が変更されます。
これを手動でテストするには、/api/draft
にアクセスして、ブラウザのデベロッパーツールを確認してください。__prerender_bypass
という名前のクッキーを含むSet-Cookie
レスポンスヘッダーが表示されます。
ステップ2:ヘッドレスCMSからRoute Handlerにアクセスする
これらの手順は、使用しているヘッドレスCMSがカスタムドラフトURLの設定をサポートしていることを前提としています。サポートしていない場合でも、この方法を使用してドラフトURLを保護できますが、ドラフトURLを手動で構築してアクセスする必要があります。具体的な手順は使用するヘッドレスCMSによって異なります。
ヘッドレスCMSから安全にRoute Handlerにアクセスするには:
- お好みのトークン生成ツールを使用して秘密トークン文字列を作成します。この秘密はNext.jsアプリとヘッドレスCMSのみが知っているものになります。
- ヘッドレスCMSがカスタムドラフトURLの設定をサポートしている場合は、ドラフトURLを指定します(これはRoute Handlerが
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}
- Route Handlerで、秘密が一致することと
slug
パラメータが存在することを確認し(存在しない場合はリクエストを失敗させる)、draftMode.enable()
を呼び出してクッキーを設定します。その後、ブラウザを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')
// secretとnextパラメータを確認
// この秘密はこのRoute HandlerとCMSのみが知っているべきです
if (secret !== 'MY_SECRET_TOKEN' || !slug) {
return new Response('Invalid token', { status: 401 })
}
// 提供された`slug`が存在するかを確認するためにヘッドレスCMSからフェッチ
// getPostBySlugはヘッドレスCMSへの必要なフェッチロジックを実装します
const post = await getPostBySlug(slug)
// slugが存在しない場合、ドラフトモードの有効化を防止
if (!post) {
return new Response('Invalid slug', { status: 401 })
}
// クッキーを設定してドラフトモードを有効化
const draft = await draftMode()
draft.enable()
// フェッチされた投稿のパスにリダイレクト
// オープンリダイレクト脆弱性を防ぐためsearchParams.slugにはリダイレクトしません
redirect(post.slug)
}
成功すると、ブラウザはドラフトモードのクッキーを持って表示したいパスにリダイレクトされます。
ステップ3:ドラフトコンテンツをプレビューする
次のステップは、draftMode().isEnabled
の値を確認するようにページを更新することです。
クッキーが設定されたページをリクエストすると、データはビルド時ではなくリクエスト時にフェッチされます。
さらに、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からドラフトRoute Handler(secret
とslug
付き)にアクセスするか、URLを使って手動でアクセスすると、ドラフトコンテンツが表示されるようになります。また、公開せずにドラフトを更新した場合も、そのドラフトを表示できるようになります。