跳到内容
Pages 路由指南草稿模式

如何在 Next.js 中使用草稿模式预览内容

Pages 文档数据获取文档中,我们讨论了如何使用 getStaticPropsgetStaticPaths 在构建时预渲染页面(静态生成)。

当您的页面从无头 CMS 获取数据时,静态生成非常有用。然而,当您在无头 CMS 上撰写草稿并希望立即在页面上查看草稿时,它并不理想。您希望 Next.js 在请求时而非构建时渲染这些页面,并获取草稿内容而非已发布内容。您希望 Next.js 仅在这种特定情况下绕过静态生成。

Next.js 有一个名为草稿模式的功能,可以解决这个问题。以下是使用它的说明。

步骤 1:创建并访问 API 路由

如果您不熟悉 Next.js API 路由,请先查看API 路由文档

首先,创建API 路由。它可以有任何名称 - 例如 pages/api/draft.ts

在此 API 路由中,您需要对响应对象调用 setDraftMode

export default function handler(req, res) {
  // ...
  res.setDraftMode({ enable: true })
  // ...
}

这将设置一个cookie以启用草稿模式。包含此 cookie 的后续请求将触发草稿模式,从而改变静态生成页面的行为(稍后详述)。

您可以通过创建如下 API 路由并从浏览器手动访问来手动测试

pages/api/draft.ts
// simple example for testing it manually from your browser.
export default function handler(req, res) {
  res.setDraftMode({ enable: true })
  res.end('Draft mode is enabled')
}

如果您打开浏览器的开发者工具并访问 /api/draft,您会注意到一个名为 __prerender_bypassSet-Cookie 响应头。

从无头 CMS 安全访问

实际上,您会希望从无头 CMS 安全地调用此 API 路由。具体步骤将因您使用的无头 CMS 而异,但这里有一些您可以采取的常见步骤。

这些步骤假设您使用的无头 CMS 支持设置自定义草稿 URL。如果不支持,您仍然可以使用此方法来保护您的草稿 URL,但您需要手动构建和访问草稿 URL。

首先,您应该使用您选择的令牌生成器创建一个秘密令牌字符串。此秘密将仅由您的 Next.js 应用程序和您的无头 CMS 知道。此秘密可防止无权访问您的 CMS 的人访问草稿 URL。

其次,如果您的无头 CMS 支持设置自定义草稿 URL,请将以下内容指定为草稿 URL。这假设您的草稿 API 路由位于 pages/api/draft.ts

终端
https://<your-site>/api/draft?secret=<token>&slug=<path>
  • <your-site> 应该是您的部署域名。
  • <token> 应该替换为您生成的秘密令牌。
  • <path> 应该是您要查看的页面的路径。如果您要查看 /posts/foo,那么您应该使用 &slug=/posts/foo

您的无头 CMS 可能允许您在草稿 URL 中包含一个变量,以便 <path> 可以根据 CMS 的数据动态设置,如下所示:&slug=/posts/{entry.fields.slug}

最后,在草稿 API 路由中

  • 检查秘密是否匹配以及 slug 参数是否存在(如果不存在,请求应失败)。
  • 调用 res.setDraftMode
  • 然后将浏览器重定向到 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 draft mode from being enabled
  if (!post) {
    return res.status(401).json({ message: 'Invalid slug' })
  }
 
  // Enable Draft Mode by setting the cookie
  res.setDraftMode({ enable: true })
 
  // 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)
}

如果成功,浏览器将使用草稿模式 cookie 重定向到您要查看的路径。

步骤 2:更新 getStaticProps

下一步是更新 getStaticProps 以支持草稿模式。

如果您使用已设置 cookie 的页面(通过 res.setDraftMode)请求具有 getStaticProps 的页面,则 getStaticProps 将在请求时(而不是在构建时)被调用。

此外,它将使用一个 context 对象调用,其中 context.draftMode 将为 true

export async function getStaticProps(context) {
  if (context.draftMode) {
    // dynamic data
  }
}

我们在草稿 API 路由中使用了 res.setDraftMode,因此 context.draftMode 将为 true

如果您还使用 getStaticPaths,那么 context.params 也将可用。

获取草稿数据

您可以更新 getStaticProps 以根据 context.draftMode 获取不同的数据。

例如,您的无头 CMS 可能有不同的草稿文章 API 端点。如果是这样,您可以修改 API 端点 URL,如下所示

export async function getStaticProps(context) {
  const url = context.draftMode
    ? 'https://draft.example.com'
    : 'https://production.example.com'
  const res = await fetch(url)
  // ...
}

就是这样!如果您从无头 CMS 或手动访问草稿 API 路由(带 secretslug),您现在应该能够看到草稿内容。如果您在未发布的情况下更新草稿,您应该能够查看草稿。

将其设置为您无头 CMS 上的草稿 URL 或手动访问,您应该能够看到草稿。

终端
https://<your-site>/api/draft?secret=<token>&slug=<path>

更多详情

默认情况下,草稿模式会话在浏览器关闭时结束。

要手动清除草稿模式 cookie,请创建一个调用 setDraftMode({ enable: false }) 的 API 路由

pages/api/disable-draft.ts
export default function handler(req, res) {
  res.setDraftMode({ enable: false })
}

然后,向 /api/disable-draft 发送请求以调用 API 路由。如果使用 next/link 调用此路由,则必须传入 prefetch={false} 以防止在预取时意外删除 cookie。

getServerSideProps 配合使用

草稿模式与 getServerSideProps 配合使用,并可在 context 对象的 draftMode 键中获取。

须知:使用草稿模式时,您不应设置 Cache-Control 标头,因为它无法绕过。我们建议改用 ISR

与 API 路由配合使用

API 路由将能够访问请求对象上的 draftMode。例如

export default function myApiRoute(req, res) {
  if (req.draftMode) {
    // get draft data
  }
}

每个 next build 独一无二

每次运行 next build 时都会生成一个新的绕过 cookie 值。

这确保了绕过 cookie 无法被猜测。

须知:要在 HTTP 上本地测试草稿模式,您的浏览器需要允许第三方 cookie 和本地存储访问。