コンテンツにスキップ

ドラフトモード

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

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

ステップ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')
}

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

`/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`にあると想定しています)。 例:
ターミナル
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`パラメータが存在することを確認します (存在しない場合、リクエストは失敗するはずです)。 Cookieを設定するために`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)
}

成功した場合、ブラウザはドラフトモードCookieを使用して表示するパスにリダイレクトされます。

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

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

Cookieが設定されているページをリクエストすると、データは(ビルド時ではなく)**リクエスト時**に取得されます。

さらに、`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から、またはURLを手動で使用して、ドラフトルートハンドラー(`secret` と `slug` を使用)にアクセスすると、ドラフトコンテンツが表示できるようになります。また、公開せずにドラフトを更新すると、ドラフトを表示できます。

次のステップ

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