草稿模式 (Draft Mode)
在页面文档和数据获取文档中,我们讨论了如何使用 getStaticProps
和 getStaticPaths
在构建时预渲染页面(静态生成 (Static Generation))。
当您的页面从无头 CMS (headless CMS) 获取数据时,静态生成非常有用。但是,当您在无头 CMS 上撰写草稿并希望立即在页面上查看草稿时,这种方式就不理想了。此时您会希望 Next.js 在请求时 (request time) 而非构建时渲染这些页面,并获取草稿内容而非已发布的内容。您会希望 Next.js 仅针对这种情况绕过静态生成。
Next.js 的草稿模式 (Draft Mode) 功能可以解决这个问题。以下是使用说明。
步骤 1:创建并访问 API 路由
如果您不熟悉 Next.js 的 API 路由,请先查阅 API 路由文档。
首先创建 API 路由。它可以有任何名称,例如 pages/api/draft.ts
在此 API 路由中,您需要在响应对象上调用 setDraftMode
。
这将设置一个 cookie 来启用草稿模式。包含此 cookie 的后续请求将触发草稿模式 (Draft Mode),从而改变静态生成页面的行为(稍后会详细介绍)。
您可以通过手动创建如下 API 路由并从浏览器访问来进行测试:
如果您打开浏览器的开发者工具并访问 /api/draft
,您会注意到一个 Set-Cookie
响应头,其中包含名为 __prerender_bypass
的 cookie。
从无头 CMS 安全访问
实际上,您会希望从无头 CMS 安全地调用此 API 路由。具体步骤会因您使用的无头 CMS 而异,但以下是一些常见的步骤。
这些步骤假设您使用的无头 CMS 支持设置自定义草稿 URL。如果不支持,您仍然可以使用此方法来保护草稿 URL,但需要手动构建和访问草稿 URL。
首先,您应该使用您选择的令牌生成器创建一个密钥令牌字符串 (secret token string)。此密钥仅由您的 Next.js 应用和无头 CMS 知晓。此密钥可防止无权访问 CMS 的人访问草稿 URL。
其次,如果您的无头 CMS 支持设置自定义草稿 URL,请将以下内容指定为草稿 URL。这里假设您的草稿 API 路由位于 pages/api/draft.ts
。
<your-site>
应为您的部署域名。<token>
应替换为您生成的密钥令牌。<path>
应为您想要查看的页面的路径。例如,如果您想查看/posts/foo
,则应使用&slug=/posts/foo
。
您的无头 CMS 可能允许您在草稿 URL 中包含变量,以便 <path>
可以根据 CMS 的数据动态设置,例如:&slug=/posts/{entry.fields.slug}
最后,在草稿 API 路由中:
- 检查密钥是否匹配以及
slug
参数是否存在(如果不匹配或不存在,请求应失败)。 - 调用
res.setDraftMode
。 - 然后将浏览器重定向到
slug
指定的路径(以下示例使用了 307 重定向)。
如果成功,浏览器将被重定向到您想要查看的路径,并附带草稿模式 cookie。
步骤 2:更新 getStaticProps
下一步是更新 getStaticProps
以支持草稿模式。
如果您请求的页面具有 getStaticProps
并且设置了 cookie(通过 res.setDraftMode
),则 getStaticProps
将在请求时 (request time)(而非构建时)被调用。
此外,它将被调用时传入一个 context
对象,其中 context.draftMode
将为 true
。
我们在草稿 API 路由中使用了 res.setDraftMode
,因此 context.draftMode
将为 true
。
如果您还使用 getStaticPaths
,则 context.params
也将可用。
获取草稿数据
您可以根据 context.draftMode
更新 getStaticProps
以获取不同的数据。
例如,您的无头 CMS 可能有一个用于草稿文章的不同 API 端点。如果是这样,您可以按如下方式修改 API 端点 URL:
就是这样!如果您从无头 CMS 或手动访问草稿 API 路由(带有 secret
和 slug
),您现在应该能够看到草稿内容。如果您更新草稿而不发布,您应该能够查看草稿。
将此设置为无头 CMS 上的草稿 URL 或手动访问,您应该能够看到草稿。
更多详情
清除草稿模式 cookie
默认情况下,草稿模式会话会在浏览器关闭时结束。
要手动清除草稿模式 cookie,请创建一个调用 setDraftMode({ enable: false })
的 API 路由:
然后,向 /api/disable-draft
发送请求以调用 API 路由。如果使用 next/link
调用此路由,则必须传递 prefetch={false}
以防止在预取时意外删除 cookie。
与 getServerSideProps
配合使用
草稿模式可与 getServerSideProps
配合使用,并作为 context
对象中的 draftMode
键使用。
须知:使用草稿模式时不应设置
Cache-Control
标头,因为它无法绕过。相反,我们建议使用 ISR (增量静态再生)。
与 API 路由配合使用
API 路由将在请求对象上访问 draftMode
。例如:
每次 next build
时唯一
每次运行 next build
时,都会生成一个新的绕过 cookie 值。
这确保绕过 cookie 无法被猜测。
须知:要通过 HTTP 在本地测试草稿模式,您的浏览器需要允许第三方 cookie 和本地存储访问。