Lang x Lang

Preview Mode

注意: この機能はDraft Modeによって上書きされます。

Examples

Pages ドキュメントData Fetching ドキュメントで、getStaticPropsgetStaticPaths を使用してビルド時にページをプレレンダリングする方法(Static Generation)について説明しました。

Static Generation はページがヘッドレス CMS から fetch データを取得するときに便利です。しかし、ヘッドレス CMS で下書きを書いて、その下書きをページですぐにpreviewしたい場合には理想的ではありません。この場合、あなたは Next.js にこれらのページを build 時間ではなく、request 時に render し、公開されたコンテンツではなく下書きのコンテンツを fetch するようにしたいでしょう。あなたはこの特定のケースだけで Next.js に Static Generation をバイ path してもらいたいのです。

Next.js は、この問題を解決するPreview モードという機能を持っています。それの使い方についての指示は以下の通りです。

Step 1: Create and access a preview API route

Next.js の API Routes に慣れていない場合は、まず API Routes ドキュメントをご覧ください。

まず、preview API routeを作成します。任意の名前を付けることができます - 例えば pages/api/preview.js (あるいは TypeScript を使用している場合は .ts)。

この API route では、response object でsetPreviewDataを呼び出す必要があります。setPreviewDataの引数は object であり、これはgetStaticPropsで使用できます(これについては後ほど詳しく説明します)。今のところ、我々は{}を使用します。

export default function handler(req, res) {
  // ...
  res.setPreviewData({});
  // ...
}

res.setPreviewDataはブラウザにいくつかのcookiesを設定し、preview モードをオンにします。これらの cookies を含む Next.js へのすべての Request は、preview モードとみなされ、静的に生成されたページの動作が変更されます(詳しくは後述します)。

以下のような API ルートを作成し、ブラウザから手動でアクセスすることで、これを手動でテストすることができます:

pages/api/preview.js
// simple example for testing it manually from your browser.
export default function handler(req, res) {
  res.setPreviewData({})
  res.end('Preview mode enabled')
}

ブラウザの開発者ツールを開いて/api/previewにアクセスすると、__prerender_bypass__next_preview_data の cookies がこの request に設定されることに気づくでしょう。

Securely accessing it from your Headless CMS

実際には、ヘッドレス CMS からこの API ルートを 安全に 呼び出すことを望むでしょう。使用しているヘッドレス CMS によって具体的なステップは異なりますが、ここにいくつかの一般的なステップを示します。

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

まず、お好みのトークンジェネレーターを使用して、secret トークン stringを作成する必要があります。この secret は、あなたの Next.js app とヘッドレス CMS だけが知っています。この secret は、CMS へのアクセス権がない人々が preview URL にアクセスするのを防ぎます。

次に、ヘッドレス CMS がカスタム preview URL の設定をサポートしている場合は、次の URL を preview URL として指定します。これは、 preview API route がpages/api/preview.jsに位置していることを前提としています。

Terminal
https://<your-site>/api/preview?secret=<token>&slug=<path>
  • <your-site>はデプロイメントドメインであるべきです。
  • <token>は生成したシークレットトークンに置き換えるべきです。
  • <path>は、preview したいページの path であるべきです。 /posts/fooを preview したい場合は、&slug=/posts/fooを使用するべきです。

あなたのヘッドレス CMS では、<path>が CMS のデータに基づいて動的に設定できるように、variable を preview URL に含めることが可能かもしれません。例えば、&slug=/posts/{entry.fields.slug}のようにします。

最後に、 preview API route で:

  • secret が一致していること、そしてslugパラメータが存在することを確認します(存在しない場合、リクエストは失敗するべきです)。
  • res.setPreviewDataを呼び出してください。
  • 次に、slugで指定されたパスにブラウザをリダイレクトします(以下の例では307 リダイレクト を使用しています)。
export default async (req, res) => {
  // Check the secret and next parameters
  // This secret should only be known to this API route and the CMS
  if (req.query.secret !== "MY_SECRET_TOKEN" || !req.query.slug) {
    return res.status(401).json({ message: "Invalid token" });
  }

  // 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(req.query.slug);

  // If the slug doesn't exist prevent preview mode from being enabled
  if (!post) {
    return res.status(401).json({ message: "Invalid slug" });
  }

  // Enable Preview Mode by setting the cookies
  res.setPreviewData({});

  // Redirect to the path from the fetched post
  // We don't redirect to req.query.slug as that might lead to open redirect vulnerabilities
  res.redirect(post.slug);
};

成功すれば、ブラウザはあなたが preview モードで cookies が設定された状態で preview したい path に Redirect されます。

Step 2: Update getStaticProps

次の next ステップは、 preview モードをサポートするためにgetStaticPropsを更新することです。

もし、getStaticPropsを持つページを request し、その際に preview モードの cookies が res.setPreviewData によってセットされた場合、getStaticPropsrequest 時( build 時ではなく)で呼び出されます。

さらに、それはcontext object で呼び出されます。その場合、次のようになります:

  • context.previewtrueになります。
  • context.previewDatasetPreviewDataに使用される引数と同じになります。
export async function getStaticProps(context) {
  // If you request this page with the preview mode cookies set:
  //
  // - context.preview will be true
  // - context.previewData will be the same as
  //   the argument used for `setPreviewData`.
}

私たちは preview API route でres.setPreviewData({})を使用したので、context.previewData{}になります。必要であれば、この機能を使って preview API route からgetStaticPropsにセッション情報を送ることができます。

getStaticPathsも使用している場合は、context.paramsも利用可能になります。

Fetch preview データ

あなたはgetStaticPropsを更新して、context.previewおよび/またはcontext.previewDataに基づいて異なるデータを fetch できます。

例えば、あなたのヘッドレス CMS は、下書きの投稿用の異なる API エンドポイントを持つかもしれません。その場合、context.previewを使用して、以下のように API エンドポイントの URL を変更することができます:

export async function getStaticProps(context) {
  // If context.preview is true, append "/preview" to the API endpoint
  // to request draft data instead of published data. This will vary
  // based on which headless CMS you're using.
  const res = await fetch(`https://.../${context.preview ? "preview" : ""}`);
  // ...
}

それで終わりです!あなたがヘッドレス CMS から、または手動で preview API route(secretおよびslugを使用して)にアクセスすると、今では preview コンテンツを見ることができるはずです。また、公開せずにドラフトを更新すると、ドラフトを preview することができるはずです。

この URL をヘッドレス CMS の preview URL に設定するか、手動でアクセスすれば、preview を見ることができるはずです。

Terminal
https://<your-site>/api/preview?secret=<token>&slug=<path>

More Details

Good to know: レンダリング中に、next/routerisPreview フラグを公開します。詳細については、router object ドキュメントをご覧ください。

Preview モードの持続時間を指定してください

setPreviewDataはオプショナルな second パラメータを取ります。これは options object であるべきです。以下のキーを受け付けます:

  • maxAge: preview セッションが続く number (秒単位)を指定します。
  • path: cookie が適用されるべき paths を指定します。default では、/が設定され、全ての path に対して preview モードが有効になります。
setPreviewData(data, {
  maxAge: 60 * 60, // The preview mode cookies expire in 1 hour
  path: "/about", // The preview mode cookies apply to paths with /about
});

Preview モードの cookies をクリアする

default では、 Preview モードの cookies に有効期限の date が設定されていません。したがって、 preview セッションは、ブラウザを閉じたときに終了します。

Preview モードの cookies を手動でクリアするには、clearPreviewData() を呼び出す API route を作成します。

pages/api/clear-preview-mode-cookies.js
export default function handler(req, res) {
  res.clearPreviewData({})
}

次に、/api/clear-preview-mode-cookiesに対して request を送信して、 API Route を呼び出します。この route をnext/linkを使用して呼び出す場合、clearPreviewDataが link の prefetching 中に呼び出されるのを防ぐためにprefetch={false}を渡す必要があります。

setPreviewDataの呼び出しで path が指定された場合、同じ path をclearPreviewDataに渡さなければなりません。

pages/api/clear-preview-mode-cookies.js
export default function handler(req, res) {
  const { path } = req.query

  res.clearPreviewData({ path })
}

previewData size の制限

setPreviewDataに object を渡して、getStaticPropsで利用できるようにすることが可能です。ただし、データは cookie に保存されるため、size 制限があります。現在、preview データは 2KB に制限されています。

Works with getServerSideProps

getServerSidePropsでも preview モードが機能します。これはまた、previewpreviewDataを含むcontext object でも利用可能になります。

Good to know: Cache-Controlの header を Preview モードで使用する際に設定するべきではありません。これはバイパスできません。代わりに、ISRの使用をお勧めします。

Works with API Routes

API Routes は、request object の下でpreviewおよびpreviewDataにアクセスできます。例えば:

export default function myApiRoute(req, res) {
  const isPreview = req.preview;
  const previewData = req.previewData;
  // ...
}

Unique per next build

バイパスの cookie value と、previewDataを暗号化するためのプライベートキーは、next buildが完了すると変更されます。これにより、バイパスの cookie が推測されることはありません。

Good to know: test Preview モードをローカルの HTTP 上でテストするためには、ブラウザがサードパーティの cookies とローカルストレージへのアクセスを許可する必要があります。

当社サイトでは、Cookie を使用しています。各規約をご確認の上ご利用ください:
Cookie Policy, Privacy Policy および Terms of Use