本文详解 Next.js 项目中无法及时获取 Sanity 最新内容的根本原因(客户端/服务端缓存、静态生成策略及实时订阅缺失),并提供清除缓存、启用 ISR、配置 useLiveMode 及 groq 查询优化等完整解决方案。
本文详解 next.js 项目中无法及时获取 sanity 最新内容的根本原因(客户端/服务端缓存、静态生成策略及实时订阅缺失),并提供清除缓存、启用 isr、配置 `uselivemode` 及 `groq` 查询优化等完整解决方案。
在 Next.js 中集成 Sanity CMS 时,常遇到“Studio 已发布新内容,但前端页面仍显示旧数据”的问题——即使刷新页面、重启开发服务器甚至部署到生产环境,变更依然不生效。这并非 Sanity 同步失败,而是 Next.js 的数据获取机制与缓存策略共同导致的典型现象。
根本原因:缓存层叠加干扰
- 客户端缓存:浏览器对 fetch 请求(尤其 GET)可能复用响应;
- Next.js 服务端缓存:getStaticProps 默认静态生成(SSG),构建时抓取快照,后续请求均返回该静态 HTML,除非手动触发重生成;
- CDN/边缘缓存:Vercel 等平台对静态资源自动缓存,进一步延迟更新;
- 未启用实时订阅:默认 fetch 是一次性请求,不监听后续变更。
✅ 正确解决方案(按推荐顺序)
1. 优先使用 getServerSideProps(SSR)快速验证
适用于内容高频更新或需强一致性场景:
// pages/index.tsx
export async function getServerSideProps() {
const client = createClient({
projectId: 'your-project-id',
dataset: 'production',
useCdn: false, // 关键:禁用 CDN 缓存,直连 API
});
const posts = await client.fetch(`*[_type == "post"]`);
return { props: { posts } };
}
✅ 优势:每次请求都实时拉取最新数据;❌ 缺点:增加服务器负载,牺牲部分性能。
2. 启用增量静态再生(ISR)——生产推荐方案
保留 SSG 性能,同时支持后台更新:
// pages/index.tsx
export async function getStaticProps() {
const client = createClient({ projectId: 'xxx', dataset: 'production', useCdn: true });
const posts = await client.fetch(`*[_type == "post"]`);
return {
props: { posts },
revalidate: 60, // 每 60 秒尝试重新生成页面(秒)
};
}
⚠️ 注意:revalidate 仅在有用户访问该路径时触发,且需确保 useCdn: true(利用 Sanity CDN 缓存 + Next.js ISR 协同)。
3. 客户端实时订阅(Live Mode)
在页面组件中启用自动更新(适合管理后台或编辑预览):
import { useLiveMode } from 'next-sanity';
import { useSanityClient } from 'sanity';
export default function BlogPage() {
const client = useSanityClient();
const [posts, setPosts] = useState([]);
useLiveMode(() => {
client
.fetch(`*[_type == "post"]`)
.then(setPosts);
});
return (
<div>{posts.map(p => <h2 key="{p._id}">{p.title}</h2>)}</div>
);
}
? 需安装 next-sanity 并配置 useLiveMode(底层基于 Sanity 的 @sanity/client 实时订阅能力)。
4. 强制清除缓存(调试阶段)
- 开发时:添加 cache: 'no-store' 到 fetch 选项:
const data = await fetch(url, { cache: 'no-store' }); - 生产时:Vercel 控制台 → Settings → Cache → Purge Cache;或调用 Vercel API 清除指定路径。
⚠️ 关键注意事项
- 避免 useCdn: false 在生产环境长期使用:会绕过 Sanity 全球 CDN,显著降低读取性能;
- 检查查询语句是否含 | order(_updatedAt desc):确保排序逻辑不因 _createdAt 或字段缺失导致“看似未更新”;
- 验证 _rev 和 _updatedAt 字段:在 Studio 中查看文档详情,确认发布时间戳已变更;
- 禁用 getStaticProps 时的 fallback: true:若启用,需额外处理 fallback: 'blocking' 或 false,避免 stale fallback 页面。
总结
“改了代码才更新”本质是 Next.js 缓存机制生效的表现——修改文件触发重新构建,从而重新执行 getStaticProps 抓取新数据。真正解法不是依赖代码变更,而是主动控制缓存生命周期:开发期用 SSR + no-store 快速验证;生产环境首选 ISR + CDN 组合;高交互场景补充客户端 Live Mode。三者结合,即可实现 Sanity 内容发布后秒级同步至 Next.js 前端。











