Nextjs ISR 企业落地实战
2026年3月2日 15:14
背景
Nextjs 项目本来使用的是 SSG 来渲染门户网站的 blog 的,目录如下:
![]()
这样技术实现是简单,但是维护成本比较高。运营和销售同学写完营销文章后,需要推送给研发,由研发录入到 git 仓库中,并且执行一遍发布流程。这样做,没有办法将文章撰写作为一个独立的营销任务,必须借助技术发布。而且还有个问题,blog 越来越多,放在仓库里,会导致仓库大小越来越大:
![]()
需求与技术方案设计
于是我们就设计了一个这样的内部需求:
维护一个内部的 blog 发布平台,运营录入后点击发布,同时通知 Nextjs 项目触发更新文章。
技术方案:
- 内部 blog 发布平台使用 antd + go 搭建,负责录入文章到数据库,并提供公网接口获取
- Nextjs 改造为通过接口获取动态数据,设置缓存来优化访问;并暴露 API,内部 blog 发布平台触发更新后清除缓存,用户下次访问就回去拉取最新的数据源。
初步实现
内部 blog 发布平台
没啥说的,普通的后台管理系统,如图
![]()
md 编辑器就使用掘金的 bytemd
![]()
用户录入后,存入到数据库中,并暴露接口来获取。
Nextjs 项目改造
页面配置:
export const dynamic = 'auto'; // 允许页面缓存
export const dynamicParams = true;
export const revalidate = 259200; // 页面缓存 3 天(与 fetch 缓存时间一致)
将读取静态目录换为通过接口(自己开发 API 提供数据源)获取:
// SSR 页面
const postData = {
Action: "GetPublishedArticleList",
Lang: lng,
};
const startTime = Date.now();
const res = await fetch(blogApiUrl, {
method: "POST",
headers: {
'remote_user': 'admin',
'Content-Type': 'application/json',
},
body: JSON.stringify(postData),
// 设置缓存:有效期3天(259200秒),使用标签以便外部API可以清除缓存
next: {
revalidate: 259200, // 3天
tags: [`blog-list-${lng}`],
},
});
// 拿到数据后处理
if (res.ok) {
const response = await res.json();
const count = response?.Data?.Total || 0;
...
}
...
然后暴露 API,负责清除 fetch 缓存:
![]()
该 API 要记得配置 cors 跨域和来源 ip 和频次限制。
此外,需要配置 api 请求拦截,避免被中间件等影响造成请求不到地址:
async headers() {
return [
{
// 排除 /api 路径,让 API 路由自己处理 CORS
source: "/((?!api).)*",
headers: [
{
key: "Access-Control-Allow-Origin",
value: "*", // Set your origin
},
{
key: "Access-Control-Allow-Methods",
value: "GET, POST, PUT, DELETE, OPTIONS",
},
{
key: "Access-Control-Allow-Headers",
value: "Content-Type, Authorization",
},
],
},
];
},
ISR 工作流程
首次访问:
- 服务端渲染(SSR), fetch 缓存
- 生成 HTML 并缓存
- 返回给用户
后续访问(3 天内):
- 直接返回缓存的 HTML, 不重新渲染, 响应快
3 天后:
- 第一个请求触发后台重新渲染
- 更新全部缓存
- 后续请求使用新缓存
调用 /api/revalidate-blog:
- 立即清除缓存
- 下次访问重新渲染
落地演示
新建一篇文章,点击发布,更新状态:
![]()
调用 revalidate API 触发缓存更新:
![]()
线上刷新查看:
![]()
成功!!