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

使用Sanity+Next.js:内容更新后如何清缓存,兼顾性能与实时性?

解决Sanity+Next.js下缓存与实时内容更新的矛盾

我用Sanity作为CMS、Next.js作为前端开发网站,需要配置缓存来应对一定规模的流量,但编辑在Sanity中修改内容后,希望刷新线上网站就能立即看到变更。目前我不得不添加force-dynamic阻止页面静态生成(否则内容需重新部署才更新),同时设置useCdn: false让编辑实时看到变更,但这样会导致API调用变慢、成本更高。

以下是几种兼顾性能与实时更新的解决方案:


方案1:增量静态再生(ISR)+ Sanity Webhook触发按需重验证

这是最推荐的方案,既利用静态缓存应对流量,又能在内容更新时实时触发页面重验证。

步骤1:修改组件代码恢复CDN与配置ISR

import { createClient } from "next-sanity";

const client = createClient({
  projectId: process.env.NEXT_PUBLIC_SANITY_PROJECT_ID,
  dataset: process.env.NEXT_PUBLIC_SANITY_DATASET,
  apiVersion: process.env.NEXT_PUBLIC_SANITY_API_V,
  useCdn: true, // 恢复使用Sanity CDN提升请求速度
});

export default async function Home() {
  const res = await client.fetch(
    `*[_type == "posts"] {
    _id,
    name
  }`,
  );
  return (
    <div>
      {JSON.stringify(res, null, 2)}
    </div>
  );
}

// 配置ISR:默认缓存60秒,同时支持按需触发重验证
export const revalidate = 60;

步骤2:添加重验证API路由

在app/api/revalidate/route.js创建路由,用于接收Sanity的Webhook请求:

import { revalidatePath } from 'next/cache';
import { NextResponse } from 'next/server';

export async function POST(request) {
  // 验证请求合法性(建议配置)
  const secret = request.headers.get('x-sanity-webhook-secret');
  if (secret !== process.env.SANITY_WEBHOOK_SECRET) {
    return new NextResponse('无效密钥', { status: 401 });
  }

  try {
    // 重验证首页路径,若有其他页面可按需添加
    revalidatePath('/');
    return NextResponse.json({ 重验证成功: true, 时间: Date.now() });
  } catch (err) {
    return new NextResponse('重验证失败', { status: 500 });
  }
}

步骤3:配置Sanity Webhook

在Sanity Studio的设置中添加Webhook:

  • 触发条件:选择「Document published」和「Document updated」
  • 目标URL:填写你的网站域名 + /api/revalidate
  • 自定义密钥:设置一个随机字符串,同步到Next.js的环境变量SANITY_WEBHOOK_SECRET

方案2:区分用户身份动态切换CDN策略

针对编辑用户禁用CDN获取实时内容,普通访客走CDN缓存,兼顾两者需求。

import { createClient } from "next-sanity";
import { cookies } from "next/headers";

// 动态创建客户端,根据用户身份切换CDN配置
export async function getClient() {
  const cookieStore = cookies();
  // 假设编辑登录后会设置`editorLoggedIn`标识cookie
  const isEditor = cookieStore.get('editorLoggedIn')?.value === 'true';

  return createClient({
    projectId: process.env.NEXT_PUBLIC_SANITY_PROJECT_ID,
    dataset: process.env.NEXT_PUBLIC_SANITY_DATASET,
    apiVersion: process.env.NEXT_PUBLIC_SANITY_API_V,
    useCdn: !isEditor, // 编辑用户禁用CDN,普通用户启用
  });
}

export default async function Home() {
  const client = await getClient();
  const res = await client.fetch(
    `*[_type == "posts"] {
    _id,
    name
  }`,
  );
  return (
    <div>
      {JSON.stringify(res, null, 2)}
    </div>
  );
}

// 配置ISR缓存,普通访客享受静态缓存加速
export const revalidate = 60;

方案3:专属预览页面隔离实时需求

给编辑提供单独的预览页面,利用Sanity的实时订阅功能查看内容变更,正式页面保持静态/ISR缓存,完全不影响性能。

实现思路:

  1. 在Next.js中添加带权限验证的预览路由
  2. 预览页面使用Sanity的sync订阅功能监听内容变更
  3. 编辑通过专属预览链接查看实时内容,正式页面依然走缓存

内容的提问来源于stack exchange,提问作者Evanss

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 09:40:29