はじめに/ガイド/Draft Mode

Next.jsでDraft Modeを使用してコンテンツをプレビューする方法

Draft Modeを使用すると、ヘッドレスCMSの下書きコンテンツをNext.jsアプリケーションでプレビューできます。ビルド時に生成される静的ページで便利で、動的レンダリングに切り替えて、サイト全体を再ビルドせずに下書きの変更を確認できます。

このページでは、Draft Modeを有効化して使用する方法を説明します。

ステップ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('Draft mode is enabled')
}

これにより、Draft Modeを有効化するCookieが設定されます。このCookieを含む後続のリクエストはDraft Modeをトリガーし、静的に生成されたページの動作を変更します。

/api/draftにアクセスし、ブラウザの開発者ツールで確認することで手動でテストできます。__prerender_bypassという名前のCookieを含むSet-Cookieレスポンスヘッダーに注目してください。

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

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

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

  1. 任意のトークンジェネレータを使用して秘密トークン文字列を作成します。この秘密はNext.jsアプリとヘッドレスCMSのみが知っている必要があります。
  2. ヘッドレスCMSがカスタム下書きURLの設定をサポートしている場合、下書きURLを指定します(ルートハンドラがapp/api/draft/route.tsにあると仮定)。例:
Terminal
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()を呼び出して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')

  // 秘密トークンと次のパラメータを確認
  // この秘密はこのルートハンドラとCMSのみが知っている必要があります
  if (secret !== 'MY_SECRET_TOKEN' || !slug) {
    return new Response('Invalid token', { status: 401 })
  }

  // ヘッドレスCMSに問い合わせて指定された`slug`が存在するか確認
  // getPostBySlugはヘッドレスCMSへのフェッチロジックを実装します
  const post = await getPostBySlug(slug)

  // slugが存在しない場合、Draft Modeの有効化を防ぐ
  if (!post) {
    return new Response('Invalid slug', { status: 401 })
  }

  // Cookieを設定してDraft Modeを有効化
  const draft = await draftMode()
  draft.enable()

  // 取得した投稿のパスにリダイレクト
  // searchParams.slugにはリダイレクトしない(オープンリダイレクト脆弱性の可能性があるため)
  redirect(post.slug)
}

成功すると、ブラウザはDraft Mode 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から(secretslugを使用して)下書きルートハンドラにアクセスするか、URLを手動で使用すると、下書きコンテンツを表示できるようになります。また、公開せずに下書きを更新した場合、その下書きを表示できるはずです。

On this page