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

Next.js ISR动态页面在Headless WordPress CMS删除后未失效问题

问题根因

你遇到的问题是Next.js ISR机制和Apollo Client缓存共同作用的结果:

  1. Next.js ISR的默认逻辑是,已经生成的静态页面会在缓存有效期内直接返回给用户,只有等到你设置的revalidate:10的10秒窗口到了之后,才会在后台重新执行getStaticProps拉取最新数据。
  2. 你初始化的Apollo Client默认开启了内存缓存,服务端执行getStaticProps拉取数据时会直接命中本地缓存的旧数据,就算你CMS里已经删除了文章,查询结果还是会返回已删除的文章内容,不会触发notFound: true的逻辑。
  3. 首页数组长度判断存在bug:你写的if (data.posts.edges === 0),数组判断长度要改为if (data.posts.edges.length === 0)。

解决方案

1. 修复Apollo缓存问题

在所有服务端调用的Apollo查询中添加fetchPolicy: 'no-cache',强制每次都拉取最新的CMS数据,避免命中本地缓存。
修改/blog/[slug].js中的getStaticProps查询代码:

const result = await client.query({
  query: gql`
    query GetWordPressPostBySlug($id: ID!) {
      post(id: $id, idType: SLUG) {
        title
        content
      }
    }
  `,
  variables: { id: slug },
  fetchPolicy: 'no-cache' // 新增这行禁用缓存
});

同样修改首页index.js的getStaticProps查询,也加上fetchPolicy: 'no-cache'参数。

2. 优化fallback配置(可选)

将getStaticPaths返回的fallback: true改为fallback: 'blocking',这样用户访问未生成的路径时,服务端会先执行getStaticProps查询数据,不存在直接返回404,不会触发前端的Loading状态,体验更好。

3. 实现即时失效(按需ISR)

如果不需要等10秒的缓存窗口,希望CMS删除文章后前端立刻生效,可以添加按需重生成的API路由:

  1. 新建pages/api/revalidate.js,代码如下:
export default async function handler(req, res) {
  // 校验请求合法性,SECRET自己在环境变量中配置
  if (req.query.secret !== process.env.REVALIDATE_SECRET) {
    return res.status(401).json({ message: '非法请求' });
  }
  try {
    const slug = req.query.slug;
    // 重生成首页
    await res.revalidate('/');
    // 重生成对应文章页
    await res.revalidate(`/blog/${slug}`);
    return res.json({ success: true });
  } catch (e) {
    return res.status(500).json({ message: '重生成失败' });
  }
}
  1. 在WordPress后台配置Webhook,触发条件为文章删除,请求地址为你的站点地址+/api/revalidate?secret=你配置的SECRET&slug={删除文章的slug},即可实现删除文章后页面即时更新。

修改完成后,当已缓存的文章页到达revalidate时间时,Next.js会后台拉取最新数据,发现文章已删除就会返回404,下次用户访问就会看到404页面了。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.17 02:06:03