使用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缓存,完全不影响性能。
实现思路:
- 在Next.js中添加带权限验证的预览路由
- 预览页面使用Sanity的
sync订阅功能监听内容变更 - 编辑通过专属预览链接查看实时内容,正式页面依然走缓存
内容的提问来源于stack exchange,提问作者Evanss
相关产品推荐
相关产品推荐

