如何判断Vercel上Next.js的按需重新验证是否正在进行?
问题分析
你当前的Sanity客户端配置仅通过process.env.CI判断是否使用CDN,构建阶段(CI环境)能正确获取最新数据,但按需重新验证时,由于CI变量不存在,客户端默认启用CDN,而Sanity CDN可能仍缓存旧内容,导致重新生成的页面数据过时。核心需求是在按需重新验证场景下,强制Sanity客户端调用实时API而非CDN。
解决方案
方案1:重构Sanity客户端为工厂函数(推荐)
将全局配置改为可动态覆盖useCdn参数的工厂函数,按需在不同场景下切换CDN状态:
import { createClient, ClientConfig } from "@sanity/client"; // 支持自定义useCdn选项的工厂函数 export const createSanityClient = (options?: { useCdn?: boolean }) => { // 默认逻辑:CI环境禁用CDN,常规请求启用CDN const defaultUseCdn = !process.env.CI; // 允许传入选项覆盖默认值 const useCdn = options?.useCdn ?? defaultUseCdn; return createClient({ dataset: process.env.NEXT_PUBLIC_SANITY_DATASET || "production", projectId: process.env.NEXT_PUBLIC_SANITY_PROJECT_ID || "", apiVersion: "2022-01-05", useCdn, }); };
使用方式:
- 在常规页面/组件中,直接使用默认配置:
const client = createSanityClient() - 在按需重新验证的触发逻辑(如Sanity webhook对应的API路由)或页面生成逻辑中,显式禁用CDN:
// 重新验证时获取最新数据 const client = createSanityClient({ useCdn: false }); const latestData = await client.fetch(`*[_type == "your-document-type"]`);
方案2:通过自定义请求头标记重新验证场景
在触发重新验证时,发送带自定义头的请求到目标页面,让页面生成时自动禁用CDN:
- 修改重新验证API路由(
app/api/revalidate/route.ts):
import { revalidatePath } from "next/cache"; import { NextResponse } from "next/server"; export async function POST(request: Request) { const targetPath = "/"; // 替换为你需要重新验证的路径 await revalidatePath(targetPath); // 发送带自定义头的请求,强制页面获取最新数据 await fetch(`${process.env.NEXT_PUBLIC_APP_URL}${targetPath}`, { headers: { "X-Force-Fresh": "true" }, cache: "no-store", }); return NextResponse.json({ revalidated: true }); }
- 在页面的服务器组件中检查请求头:
import { createSanityClient } from "@/lib/sanity"; import { headers } from "next/headers"; export default async function Home() { const requestHeaders = headers(); const isForceFresh = requestHeaders.get("X-Force-Fresh") === "true"; // 强制刷新时禁用CDN const client = createSanityClient({ useCdn: !isForceFresh }); const data = await client.fetch(`*[_type == "your-document-type"][0]`); return <div>{data.title}</div>; }
方案3:基于Vercel内部环境变量判断(风险提示)
部分用户反馈Vercel在执行按需重新验证时会设置VERCEL_REVALIDATION环境变量(非官方公开),可尝试直接修改全局配置:
export const config: ClientConfig = { dataset: process.env.NEXT_PUBLIC_SANITY_DATASET || "production", projectId: process.env.NEXT_PUBLIC_SANITY_PROJECT_ID || "", apiVersion: "2022-01-05", // CI环境或重新验证场景禁用CDN useCdn: !process.env.CI && !process.env.VERCEL_REVALIDATION, };
⚠️ 注意:此方法依赖Vercel内部未公开的环境变量,存在变更风险,仅作为备选方案。
内容的提问来源于stack exchange,提问作者Gustavo Straube
相关产品推荐
相关产品推荐

