You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何判断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:

  1. 修改重新验证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 });
}
  1. 在页面的服务器组件中检查请求头:
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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 21:24:27