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

Next.js社交应用SSR数据不更新问题求助(Sanity CMS存储)

Next.js + Sanity 部署后数据无法实时更新的解决方案

1. 修正 Next.js 的请求缓存配置

部署后 Next.js 会默认对请求做缓存优化,即便用 SSR 也可能导致数据不更新,需手动禁用缓存:

  • App Router(React Server Components):在 fetch 请求中显式设置缓存策略
    const fetchSanityData = async () => {
      const res = await fetch(`${process.env.NEXT_PUBLIC_SANITY_API_URL}/v2024-01-01/data/query/production`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ query: '*[_type == "post"]' }),
        cache: 'no-store' // 完全禁用缓存
      })
      return res.json()
    }
    
  • Pages Router:在 getServerSideProps 中设置响应头,避免页面被缓存
    export async function getServerSideProps(context) {
      // 获取 Sanity 数据
      const data = await sanityClient.fetch('*[_type == "post"]')
      
      // 设置无缓存头
      context.res.setHeader(
        'Cache-Control',
        'no-store, no-cache, must-revalidate, proxy-revalidate'
      )
      
      return { props: { data } }
    }
    

2. 调整 Sanity 客户端的缓存策略

Sanity 的 CDN 默认会缓存请求结果,需针对性配置:

  • 直接关闭 CDN 缓存(适合需要强实时的场景)
    import { createClient } from '@sanity/client'
    
    const sanityClient = createClient({
      projectId: '你的项目ID',
      dataset: 'production',
      apiVersion: '2024-01-01',
      useCdn: false // 关闭 CDN,每次请求直接命中 Sanity 后端
    })
    
  • 若需保留 CDN 加速,可添加时间戳参数绕过缓存
    const data = await sanityClient.fetch('*[_type == "post"]', {}, {
      cache: 'no-cache',
      headers: { 'Cache-Control': 'no-cache' }
    })
    

3. 解决浏览器端静态资源缓存问题

部署后的 JS/CSS 或 HTML 可能被浏览器缓存,需在 next.config.js 中配置全局缓存策略:

/** @type {import('next').NextConfig} */
const nextConfig = {
  headers: async () => [
    {
      source: '/(.*)',
      headers: [
        {
          key: 'Cache-Control',
          value: 'no-store, no-cache, must-revalidate, max-age=0'
        }
      ]
    }
  ]
}

module.exports = nextConfig

4. 启用 Sanity 实时订阅(适配社交应用实时需求)

单纯依赖 SSR 刷新无法满足社交应用的实时更新,需在客户端监听数据变化:

import { useEffect, useState } from 'react'
import { createClient } from '@sanity/client'
import { subscribe } from '@sanity/client/subscribe'

const sanityClient = createClient({ /* 你的配置 */ })

export default function PostFeed() {
  const [posts, setPosts] = useState([])

  useEffect(() => {
    // 订阅 Sanity 数据变更
    const subscription = subscribe(sanityClient, { query: '*[_type == "post"]' })
      .subscribe({
        next: (update) => setPosts(update.result),
        error: (err) => console.error('订阅失败:', err)
      })

    // 组件卸载时取消订阅
    return () => subscription.unsubscribe()
  }, [])

  return (
    <div className="feed">
      {posts.map(post => <Post key={post._id} data={post} />)}
    </div>
  )
}

5. 结合 ISR + Sanity Webhook 实现精准更新

如果使用静态生成(SSG),可通过增量静态再生(ISR)配合 Webhook 实现内容更新时自动刷新页面:

  1. 配置页面的 revalidate 属性
    export async function getStaticProps() {
      const data = await sanityClient.fetch('*[_type == "post"]')
      return { props: { data }, revalidate: 60 } // 每60秒自动再生,或通过Webhook触发
    }
    
  2. 创建 Next.js 重验证 API 路由
    // pages/api/revalidate.js
    export default async function handler(req, res) {
      if (req.query.secret !== process.env.SANITY_WEBHOOK_SECRET) {
        return res.status(401).json({ message: '密钥无效' })
      }
    
      try {
        await res.revalidate('/') // 重验证首页
        return res.json({ revalidated: true })
      } catch (err) {
        return res.status(500).send('重验证失败')
      }
    }
    
  3. 在 Sanity 后台配置 Webhook,指向该 API 路由,设置「内容发布时触发」

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 19:09:29