Next.js ISR动态页面在Headless WordPress CMS删除后未失效问题
问题根因
你遇到的问题是Next.js ISR机制和Apollo Client缓存共同作用的结果:
- Next.js ISR的默认逻辑是,已经生成的静态页面会在缓存有效期内直接返回给用户,只有等到你设置的
revalidate:10的10秒窗口到了之后,才会在后台重新执行getStaticProps拉取最新数据。 - 你初始化的Apollo Client默认开启了内存缓存,服务端执行
getStaticProps拉取数据时会直接命中本地缓存的旧数据,就算你CMS里已经删除了文章,查询结果还是会返回已删除的文章内容,不会触发notFound: true的逻辑。 - 首页数组长度判断存在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路由:
- 新建
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: '重生成失败' }); } }
- 在WordPress后台配置Webhook,触发条件为文章删除,请求地址为你的站点地址+
/api/revalidate?secret=你配置的SECRET&slug={删除文章的slug},即可实现删除文章后页面即时更新。
修改完成后,当已缓存的文章页到达revalidate时间时,Next.js会后台拉取最新数据,发现文章已删除就会返回404,下次用户访问就会看到404页面了。
内容的提问来源于stack exchange,提问作者Mark
相关产品推荐
相关产品推荐

