
使用 Build Output API 实现 Draft Mode基于 Prerender Functions 的草稿模式缓存绕过方案【免费下载链接】examplesEnjoy our curated collection of examples and solutions. Use these patterns to build your own robust and scalable applications.项目地址: https://gitcode.com/GitHub_Trending/examples1/examples导读本文基于 build-output-api/draft-mode 预构建部署示例讲解如何在 Vercel Build Output API 的 Prerender Functions 之上实现 Draft Mode草稿模式通过构建期生成的随机bypassToken与__prerender_bypassCookie让拥有权限的用户在草稿文章正式发布前实时看到最新内容同时绕开 Prerender Function 的缓存。读完本文你将掌握prerender-config.json中bypassToken的配置方式、Cookie 的写入/清除调用链以及如何基于仓库内完整的.vercel/output构建产物搭建一套可运行、可验证的草稿模式示例。一、背景Build Output API 与 Prerender FunctionsVercel 的Build Output API允许你在自己的构建系统中生成完全符合 Vercel 部署格式的产物即 Prebuilt Deployment随后通过vercel deploy --prebuilt直接部署无需依赖 Next.js 等框架的官方构建流程。仓库的 build-output-api/README.md 列出了该目录下的全部示例包括 Routes、Serverless Functions、Static Files、On-Demand ISR、Prerender Functions 等。其中Prerender Functions是本文的核心前置概念。根据仓库中 prerender-functions/README.md 的说明Prerender Function 本质上是一个 Serverless Function以.func目录形式存在例如.vercel/output/functions/blog/page.func与.func目录同级的name.prerender-config.json是其配套配置文件config.json中的 route 规则负责把特定路径前缀如/blog/*的请求路由到该 Prerender Function未被渲染过的路径可配置可选的 fallback 文件兜底。Prerender Function 最大的特点在于带缓存Vercel 会在函数首次执行后缓存其响应直到缓存过期由expiration字段控制。缓存带来了性能收益但也带来一个问题——如果编辑正在撰写中的草稿文章刷新页面时看到的永远是缓存的旧内容这显然无法接受。Draft Mode 正是为解决这一矛盾而设计。二、Draft Mode 的核心机制bypassToken 与 __prerender_bypass Cookie关联文档 README.md 给出了 Draft Mode 的完整工作机制在 Prerender Function 对应的name.prerender-config.json文件中将bypassToken设置为构建期生成的随机字符串该字符串绝不能暴露给普通用户或客户端只允许在通过认证的情况下使用需要启用草稿模式时由一个 Serverless Function如登录函数写入名为__prerender_bypass的 Cookie其值等于bypassToken当携带该 Cookie 的请求访问 Prerender Function 端点时Draft Mode 被激活绕过 Vercel 在非草稿模式下提供的全部缓存。也就是说bypassToken是进入草稿模式的钥匙Cookie 是携带钥匙的通行证二者必须完全匹配才能生效。三、仓库源码级解析一份完整的 Draft Mode 构建产物本示例虽未提供框架源码但仓库中包含了完整的预构建产物位于build-output-api/draft-mode/.vercel/output/functions/目录下由三个 Serverless Function 与一个 prerender 配置文件构成。下面逐一剖析。3.1 配置文件index.prerender-config.json.vercel/output/functions/index.prerender-config.json 是 Draft Mode 的配置核心{ expiration: 60, group: 1, bypassToken: 87734ad8259d67c3c11747d3e4e112d0, allowQuery: [] }各字段说明字段值作用expiration60Prerender 缓存有效期秒即非草稿模式下响应被缓存 60 秒group1缓存分组编号同组的 Prerender Function 共享缓存失效策略bypassToken87734ad8259d67c3c11747d3e4e112d0草稿模式绕过令牌32 位随机十六进制字符串allowQuery[]允许参与缓存键的查询参数白名单此处为空即忽略所有查询参数从仓库中其他示例可印证这些字段的含义与用法build-output-api/on-demand-isr/.vercel/output/functions/index.prerender-config.json同样使用bypassToken实现按需重新验证而expiration与allowQuery的取值会直接影响缓存粒度和缓存键的计算方式。3.2 主页面函数index.func/index.jsindex.func/index.js 是响应根路径/的 Prerender Function它演示了草稿模式在运行时如何生效// The bypass token can be a randomly generated string of at least 32 characters. // This is meant to be *private* - DO NOT expose this value on the client-side. const bypassToken 87734ad8259d67c3c11747d3e4e112d0 module.exports (req, res) { res.setHeader(Content-Type, text/html; charsetutf-8) const isDraftMode typeof req.headers.cookie string req.headers.cookie.includes(__prerender_bypass${bypassToken}) const contents isDraftMode ? Draft Mode is strongENABLED/strong. Notice how the Server time below gets updated every time you refresh! : Draft Mode is strongDISABLED/strong. The server time below will only get updated once per minute. const enable isDraftMode ? a href/logoutDeactivate Draft Mode/a : a href/loginEnable Draft Mode/a res.end( h1Draft Mode Example/h1 p${contents}/p pServer time: ${new Date().toISOString()}/p p${enable}/p ) }关键点拆解令牌硬编码仅为演示源码注释明确说明bypassToken应当是至少 32 字符的随机字符串且属于私密信息不得暴露到客户端示例中直接写死是为了便于本地运行验证。Cookie 匹配是草稿模式的判定依据函数读取req.headers.cookie通过includes(__prerender_bypass${bypassToken})判断是否处于草稿模式。注意这里并未做严格的 Cookie 解析只是子串匹配——在实际生产实现中建议使用成熟的 Cookie 解析库。页面渲染差异化草稿模式下页面提示 Draft Mode is ENABLED并渲染new Date().toISOString()的服务器当前时间非草稿模式下提示 Draft Mode is DISABLED由于响应被 Vercel 缓存服务器时间在一分钟内保持不变——这正是验证缓存是否被绕过的直观信号。入口切换页面根据状态渲染/login或/logout链接构成完整的启停闭环。3.3 启用草稿模式login.func/index.jslogin.func/index.js 是启用草稿模式的 Serverless Function负责写入 Cookieconst bypassToken 87734ad8259d67c3c11747d3e4e112d0 const fiveMinutes 1000 * 60 * 5 module.exports (req, res) { // Set the __prerender_bypass cookie const expires new Date(Date.now() fiveMinutes) res.setHeader( set-cookie, __prerender_bypass${bypassToken}; Expires${expires.toUTCString()} ) // Redirect back to / res.statusCode 307 res.setHeader(location, /) res.end() }实现要点Cookie 名严格为__prerender_bypass值与bypassToken完全一致否则无法触发草稿模式通过Expires设置5 分钟有效期1000 * 60 * 5毫秒演示了临时授权的过期策略实际业务中可按需调整写入 Cookie 后以307 临时重定向回到/浏览器随即携带 Cookie 重新请求主页Draft Mode 即被激活。需要强调的是在真实场景中/login应当是一个经过身份认证的端点如校验登录态、会话或二次鉴权只有认证通过的用户才能获得草稿访问权。关联文档对此有明确告诫——bypassToken只允许在authenticated circumstances已认证场景下被使用。3.4 停用草稿模式logout.func/index.jslogout.func/index.js 负责清除 Cookie使浏览器回到缓存模式module.exports (req, res) { // Expire the __prerender_bypass cookie res.setHeader( set-cookie, __prerender_bypass; Expires${new Date(0).toUTCString()} ) // Redirect back to / res.statusCode 307 res.setHeader(location, /) res.end() }其做法是将同名 Cookie 置空并把Expires设为new Date(0).toUTCString()即 1970-01-01历史上最早的过期时间强制浏览器立即丢弃该 Cookie随后同样 307 重定向回/。至此草稿模式关闭后续请求重新落入 60 秒缓存策略。四、完整运行链路与验证方法将以上三个函数与配置文件组合起来一次完整的 Draft Mode 会话如下访问 /无 Cookie → Prerender Function 命中缓存返回DISABLED 固定服务器时间 ↓ 点击 Enable Draft Mode 访问 /login → login.func 写入 __prerender_bypass Cookie307 重定向回 / ↓ 浏览器携带 Cookie 重新请求 访问 / → Draft Mode 激活绕过缓存服务器时间每次刷新都更新 ↓ 点击 Deactivate Draft Mode 访问 /logout → logout.func 过期 Cookie307 重定向回 / 访问 / → 恢复缓存模式服务器时间回到每分钟更新一次你可以直接在本地或 Vercel 上运行该示例验证进入 build-output-api/draft-mode 目录参照 build-output-api/README.md 的说明执行vercel deploy --prebuilt完成预构建部署该示例的在线演示地址为https://build-output-api-draft-mode.vercel.sh反复刷新首页观察 Server time 是否每分钟只更新一次缓存生效点击 Enable Draft Mode 后再刷新观察服务器时间是否每次都变化缓存被绕过点击 Deactivate Draft Mode 恢复原状。这一服务器时间的对比正是检验 Draft Mode 是否生效的最直观手段草稿模式下函数体每次都执行时间随之更新非草稿模式下响应被缓存时间仅在expiration: 60秒后才会变化。五、安全注意事项关联文档与仓库中的注释对bypassToken的安全性提出了明确要求这也是 Draft Mode 在生产环境中落地的关键前提构建期生成随机值bypassToken应在每次构建时随机生成示例中的固定值仅用于演示建议长度不小于 32 字符可参考仓库采用的 32 位十六进制格式绝不暴露到客户端令牌属于私密凭据一旦被泄露任何持有它的人都可构造__prerender_bypassCookie 绕过缓存读取未发布内容Cookie 只在认证后下发/login端点必须先完成用户认证再下发携带令牌的 Cookie并且应设置合理的Expires过期时间示例为 5 分钟日志与审计携带__prerender_bypassCookie 的请求在访问日志中可识别可用于审计谁在何时查看了草稿内容。同类安全问题在仓库的 on-demand-isr/README.md 中也有呼应其 Security 一节指出示例中静态的bypassToken仅为演示生产系统必须对任何能触发缓存重验证的入口施加访问控制避免恶意滥用——Draft Mode 与 On-Demand ISR 共享同一套令牌安全模型可相互参照。六、与其他 Build Output API 示例的关联Draft Mode 是 Prerender Functions 能力矩阵中的一个成员仓库中同目录的示例可以帮你建立完整的知识图谱Prerender Functions本文前置概念讲解.func目录、prerender-config.json、route 与 fallback 的基础用法On-Demand ISR与 Draft Mode 方向相反——前者用x-prerender-revalidate: bypassToken请求头在事件驱动下刷新缓存后者用__prerender_bypassCookie 为已认证用户持续绕过缓存二者共用bypassToken的安全模型Serverless Functions 与 Routes分别解释无缓存函数与路由规则帮助你判断何时该用 Prerender Function、何时用普通 Serverless Function。七、总结Draft Mode 的本质是借助 Prerender Functions 内建的bypassToken机制以 Cookie 为介质为已认证用户提供一条绕过缓存、直达最新内容的私有通道。通过index.prerender-config.json声明令牌、login.func下发 Cookie、index.func判定草稿态、logout.func回收授权四个文件构成了一个完整可运行的闭环。在生产环境中你只需把固定令牌替换为构建期随机值并在/login前加上真正的认证逻辑即可将这套模式安全地复用到草稿博客、CMS 预览、A/B 内容审核等任何需要发布前预览的场景。【免费下载链接】examplesEnjoy our curated collection of examples and solutions. Use these patterns to build your own robust and scalable applications.项目地址: https://gitcode.com/GitHub_Trending/examples1/examples创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考