コンテンツにスキップ
App Routerガイドドラフトモード

Next.js でドラフトモードを使ってコンテンツをプレビューする方法

ドラフトモードを使用すると、Next.js アプリケーションでヘッドレス CMS からのドラフトコンテンツをプレビューできます。これは、ビルド時に生成される静的ページに便利です。なぜなら、サイト全体を再ビルドせずにドラフトの変更を確認するために、動的レンダリングに切り替えることができるからです。

このページでは、ドラフトモードを有効にして使用する方法を説明します。

ステップ 1:ルートハンドラーを作成する

ルートハンドラーを作成します。名前は任意ですが、例として app/api/draft/route.ts とします。

app/api/draft/route.ts
export async function GET(request: Request) {
  return new Response('')
}

次に、draftMode 関数をインポートし、enable() メソッドを呼び出します。

app/api/draft/route.ts
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 にアクセスして、Set-Cookie レスポンスヘッダーに __prerender_bypass という名前のクッキーがあるか確認することで、これを手動でテストできます。

ステップ 2:ヘッドレス CMS からルートハンドラーにアクセスする

これらの手順は、使用しているヘッドレス CMS がカスタムドラフト URL の設定をサポートしていることを前提としています。サポートしていない場合でも、この方法でドラフト URL を保護することは可能ですが、ドラフト URL を手動で構築してアクセスする必要があります。具体的な手順は、使用しているヘッドレス CMS によって異なります。

ヘッドレス CMS からルートハンドラーに安全にアクセスするには

  1. 任意のトークンジェネレーターを使用してシークレットトークン文字列を作成します。このシークレットは、Next.js アプリとヘッドレス CMS のみで知られることになります。
  2. ヘッドレス 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}

  1. ルートハンドラーで、シークレットが一致し、slug パラメータが存在することを確認します(存在しない場合は、リクエストは失敗する必要があります)。draftMode.enable() を呼び出してクッキーを設定します。その後、ブラウザを slug で指定されたパスにリダイレクトします。
app/api/draft/route.ts
import { draftMode } from 'next/headers'
import { redirect } from 'next/navigation'
 
export async function GET(request: Request) {
  // Parse query string parameters
  const { searchParams } = new URL(request.url)
  const secret = searchParams.get('secret')
  const slug = searchParams.get('slug')
 
  // Check the secret and next parameters
  // This secret should only be known to this Route Handler and the CMS
  if (secret !== 'MY_SECRET_TOKEN' || !slug) {
    return new Response('Invalid token', { status: 401 })
  }
 
  // Fetch the headless CMS to check if the provided `slug` exists
  // getPostBySlug would implement the required fetching logic to the headless CMS
  const post = await getPostBySlug(slug)
 
  // If the slug doesn't exist prevent draft mode from being enabled
  if (!post) {
    return new Response('Invalid slug', { status: 401 })
  }
 
  // Enable Draft Mode by setting the cookie
  const draft = await draftMode()
  draft.enable()
 
  // Redirect to the path from the fetched post
  // We don't redirect to searchParams.slug as that might lead to open redirect vulnerabilities
  redirect(post.slug)
}

成功した場合、ブラウザはドラフトモードクッキーとともに、表示したいパスにリダイレクトされます。

ステップ 3:ドラフトコンテンツをプレビューする

次のステップは、draftMode().isEnabled の値をチェックするようにページを更新することです。

クッキーが設定されたページをリクエストした場合、データはビルド時ではなくリクエスト時にフェッチされます。

さらに、isEnabled の値は true になります。

app/page.tsx
// page that fetches data
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 から(secretslug を指定して)ドラフトルートハンドラーにアクセスするか、URL を使用して手動でアクセスすると、ドラフトコンテンツが表示されるはずです。また、ドラフトを公開せずに更新した場合も、ドラフトを表示できるはずです。

次のステップ

Draft Mode の使用方法の詳細については、API リファレンスを参照してください。