Menu

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

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

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

ステップ1:Route Handlerを作成する

Route Handlerを作成します。例えば、app/api/draft/route.tsのような名前にできます。

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

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

app/api/draft/route.ts
TypeScript
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にアクセスするには:

  1. お好みのトークン生成ツールを使用して秘密トークン文字列を作成します。この秘密はNext.jsアプリとヘッドレスCMSのみが知っているものになります。
  2. ヘッドレスCMSがカスタムドラフトURLの設定をサポートしている場合は、ドラフトURLを指定します(これはRoute Handlerが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. Route Handlerで、秘密が一致することとslugパラメータが存在することを確認し(存在しない場合はリクエストを失敗させる)、draftMode.enable()を呼び出してクッキーを設定します。その後、ブラウザをslugで指定されたパスにリダイレクトします:
app/api/draft/route.ts
TypeScript
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になります。

app/page.tsx
TypeScript
// データをフェッチするページ
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(secretslug付き)にアクセスするか、URLを使って手動でアクセスすると、ドラフトコンテンツが表示されるようになります。また、公開せずにドラフトを更新した場合も、そのドラフトを表示できるようになります。

次のステップ

ドラフトモードの使用方法について詳しくはAPI参照をご覧ください。