On-Demand ISR 按需增量静态再生成:基于 Build Output API 的预构建部署实战指南
On-Demand ISR 按需增量静态再生成基于 Build Output API 的预构建部署实战指南【免费下载链接】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在 Vercel 的 Build Output API 生态中预构建Prebuilt项目如何实现内容更新时才重新生成页面的按需增量静态再生成On-Demand Incremental Static Regeneration简称 On-Demand ISR本指南以仓库中 build-output-api/on-demand-isr 示例为核心详细讲解 Prerender Function 的按需缓存失效机制、x-prerender-revalidate请求头的用法、bypassToken的配置与安全实践并对照仓库内基于 Next.js 的 solutions/on-demand-isr 原生实现帮助你同时掌握 Build Output API 与 Next.js 两种落地路径。示例背景Build Output API 与预构建部署Build Output API 允许开发者绕过框架的构建流程直接提供符合规范的构建产物即预构建项目。本仓库的 build-output-api 目录集中展示了这类项目的多种形态包括 Edge Functions、Edge Middleware、Image Optimization、Prerender Functions、Overrides、Routes、Serverless Functions 与静态文件等而 On-Demand ISR 示例 正是其中讲解按需重新验证缓存的一环。在该示例中当使用Prerender Functions时你可能希望基于某个事件如用户点击按钮、Webhook 回调、数据变更通知按需On-Demand重新验证某个路径的缓存而不是依赖固定的时间窗口轮询刷新。这正是 On-Demand ISR 的适用场景事件驱动 → 精准失效 → 重新生成 → 写入缓存。Demo 行为如何验证缓存是否真的生效示例提供了在线演示README 中标明为 https://build-output-api-isr.vercel.sh页面包含两个区块HTML Content与API Content。两者实现的是同一效果只是分别作用于 HTML 响应与 API 响应两种不同的响应类型。验证缓存是否工作的方式非常直观多次刷新页面观察页面上的Server Time与API Result两个值——在刷新之间保持一致说明缓存正在生效点击任一Revalidate链接触发按需重新验证对应的值随即更新更新之后再次多次刷新会发现该值只更新了一次随后又进入缓存状态。这一行为精确对应 On-Demand ISR 的核心语义平时读取缓存仅在显式触发时重建内容重建结果立即被缓存供后续请求复用。工作原理x-prerender-revalidate 请求头与 bypassTokenOn-Demand ISR 在 Build Output API 中的底层机制并不复杂核心是一条请求头约定要对某个 Prerender Function 的路径执行重新验证只需向该路径发起一个携带x-prerender-revalidate: bypassToken请求头的GET或HEAD请求。其中的bypassToken必须与该 Prerender Function 对应的name.prerender-config.json文件中的值一致。也就是说构建产物目录中每个 Prerender Function 都会伴随一个.prerender-config.json配置文件其中记录了该函数的绕过令牌bypassToken。当带正确令牌的请求到达时缓存会被重新验证绕开 Vercel 默认提供的缓存层直接执行函数逻辑并生成新内容。需要说明的是.vercel/output/functions/下的这些构建产物如index.prerender-config.json、index.func/、revalidate.func/等是在构建阶段生成的输出文件并非仓库中静态维护的源码在阅读源码时应以 README.md 描述的文件名与行号为参照在实际部署后的构建产物中核对。示例中的路径与触发链路示例演示了三条路径的按需重新验证其中/与/data的链路完全相同只是响应类型不同路径对应产物说明/index.prerender-config.jsonbypassToken、index.func/index.js自定义重新验证处理器、revalidate.func/index.js实际触发重新验证HTML 页面内容的按需重新验证/datadata.prerender-config.jsonbypassToken、index.func/index.js自定义重新验证处理器、revalidate.func/index.js实际触发重新验证API 响应内容的按需重新验证触发链路可以概括为用户点击 Revalidate / Webhook 调用 │ ▼ 自定义重新验证处理器index.func/index.js │ ▼ 携带 x-prerender-revalidate: bypassToken 的 GET/HEAD 请求 │ ▼ revalidate.func实际触发重新验证→ 绕过缓存 → 重新生成并缓存按需生成新路径博客示例除了对已有路径做重新验证On-Demand ISR 还支持按需生成全新的路径。示例中附带了一个博客应用/blog/[slug]基础博客预渲染模板允许通过 On-Demand ISR 按需生成新路径同样受index.prerender-config.json中的bypassToken保护/blog/post-1、/blog/post-2两个初始预渲染的博客文章作为站点发布时的种子内容。这一模式非常适合内容量巨大的场景不必在构建时一次性生成全部页面而是先预渲染少量入口路径待某个 slug 被触发访问或收到 CMS Webhook时再按需生成并缓存该路径。对内容型站点而言这兼顾了静态页面的性能与动态内容的及时性。安全实践bypassToken 与 authToken任何允许外部触发重新验证的能力都必须谨慎保护README 给出了两条明确的安全指引bypassToken示例中所有路径复用了同一个静态bypassToken值仅用于演示生产环境中bypassToken应当是在构建时生成的随机字符串该字符串不应暴露给用户或客户端除非在已认证的场景下才可传递。由于x-prerender-revalidate的校验就是比对请求头中的令牌与.prerender-config.json中的值令牌一旦泄露攻击者即可随意触发全站缓存重建造成资源消耗甚至内容被篡改的风险因此随机化、构建时生成、不可客户端可见是三条底线。authToken示例中的authToken同样仅用于演示生产系统中对任何能够触发重新验证的入口都应采用行业最佳实践加以保护防止恶意滥用。换句话说即使 bypassToken 保证了请求必须携带令牌你也需要在自己的业务层如 API 路由、Serverless Function用authToken或其他鉴权机制限制谁有资格发起这次携带令牌的请求形成纵深防御。对照实现Next.js 原生 On-Demand ISR仓库源码佐证Build Output API 是底层协议而日常开发中更多直接使用 Next.js 的框架级 API。仓库中的 solutions/on-demand-isr 提供了完整的 Next.js 对照实现二者解决的问题完全相同理解它可以反过来加深对 Build Output API 机制的认识。页面端getStaticProps 固定时间窗口 ISR在 pages/index.tsx 中页面通过getStaticProps在构建期抓取数据并配置了固定时间的revalidateexport const getStaticProps: GetStaticProps async () { const products await api.list() return { props: { products, date: new Date().toTimeString(), }, } }该示例页面对应的标准 ISR 形态含revalidate: 10时间窗口在页面代码的说明片段中也有展示// This function gets called at build time on server-side. // It may be called again, on a serverless function, if // revalidation is enabled and a new request comes in export async function getStaticProps() { const res await fetch(https://.../posts) const posts await res.json() return { props: { posts, }, // Next.js will attempt to re-generate the page: // - When a request comes in // - At most once every 10 seconds revalidate: 10, // In seconds } }时间窗口 ISR 的局限在于即使数据没有变化页面也可能周期性重建而数据变化才重建正是 On-Demand ISR 的改进点——自 Next.js 12.2.0 起可以在 API Routes 中使用res.revalidate实现按需触发。触发端res.revalidate 按需重新验证仓库中真正实现按需触发的 API 路由在 pages/api/revalidate/index.ts代码极简import type { NextApiRequest, NextApiResponse } from next export default async function handler( _req: NextApiRequest, res: NextApiResponse ) { await res.revalidate(/) return res.json({ revalidated: true }) }调用该 API 路由即可按需重新验证/路径不仅会清除旧内容还会同步重新执行getStaticProps、生成新内容并缓存给下一个用户。这样页面上的revalidate时间窗口甚至可以逐步增大甚至移除把刷新时机完全交给事件电商库存变更、CMS 内容更新、Webhook、机器人推送等。批量路径与即发即忘模式当需要重新验证多个路径时需要为每个路径各调用一次revalidate。仓库页面代码给出了两种策略。并行等待所有路径完成适合要求本次触发后全部就绪的场景export default async function handler(_req, res) { // Get paths to revalidate const paths await api.pathsToRevalidate() // Revalidate every path await Promise.all(paths.map(res.revalidate)) // Return a response to confirm everything went ok return res.json({ revalidated: true }) }即发即忘fire and forget适合不关心结果、追求快速响应的场景export default async function handler(_req, res) { // Get paths to revalidate const paths await api.pathsToRevalidate() // Revalidate every path without awaiting paths.forEach(res.revalidate) // Return a response to confirm everything went ok return res.json({ revalidated: true }) }选择哪种模式需要考虑函数执行成本重新验证某个路径会运行该路径对应的getStaticPropsserverless 函数计入函数执行时间而在 API 路由中await每个路径的重新验证也会让 API 路由本身运行更久同样计入函数执行时间。因此对于大量路径如果业务上允许异步完成推荐使用即发即忘策略以控制成本。安全提示在两种实现中的一致性无论是 Build Output API 还是 Next.js 原生实现README 都反复强调同一件事暴露重新验证端点时要格外小心防止 DDoS 攻击。页面 pages/index.tsx 明确建议通过请求 key、token 等方式保护端点这与 Build Output API 示例中的bypassToken、authToken双令牌设计一脉相承。如何运行与部署预构建示例Build Output API该示例属于build-output-api目录下的预构建项目。按目录级 README 的说明在对应的示例目录内执行以下命令即可部署vercel deploy --prebuiltNext.js 原生示例solutions/on-demand-isr仓库中的 solutions/on-demand-isr/README.md 提供了另一种使用方式使用create-next-app引导项目并指定示例仓库地址此处为当前仓库中对应的解决方案目录pnpm create next-app --example https://github.com/vercel/examples/tree/main/solutions/on-demand-isr随后启动开发服务器pnpm dev应用默认运行在 http://localhost:3000。本地验证流程为访问首页记录当前 Server Time → 多次刷新确认不变 → 点击页面上的 Revalidate 按钮或直接访问/api/revalidate端点→ 刷新观察时间更新 → 再次多次刷新确认重新进入缓存状态。小结通过本指南你可以掌握两条路径下的 On-Demand ISRBuild Output API 层理解了 Prerender Function 的缓存按需失效机制即通过携带x-prerender-revalidate: bypassToken请求头的GET/HEAD请求触发重新验证bypassToken存放在对应的.prerender-config.json中且支持按需生成全新的动态路径Next.js 框架层通过仓库源码确认了res.revalidate(/)的同步重新生成语义、Promise.all并行批量与forEach即发即忘两种批量策略以及函数执行时间成本上的取舍。两者共享同一条安全底线触发重新验证的入口必须用随机化的构建期令牌与业务层鉴权双重保护避免被恶意滥用。把握住事件驱动、按需重建、缓存复用这一核心思想你就可以把静态生成的性能优势与动态内容更新的及时性同时收入囊中。【免费下载链接】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),仅供参考