SSG 是 build 时把每一页预生成、永久走 CDN(直到下次 build)。ISR 也是预生成,但 Vercel 会在背后按计划或按需重新生成。内容站怎么选,归根到底就四个数字:构建时间、新鲜度需求、函数成本、回滚难度。
问题背景
SSG(Static Site Generation)在 next build 或 astro build 时写出 HTML,每个 URL 在 out/ 或 dist/ 里成为一个文件。ISR(Incremental Static Regeneration)是 Next.js 专属:页面同样预生成,但 revalidate 秒数过后,下一次请求会在后台触发重新生成。Vercel 两个都支持,但 ISR 需要 Node serverless 函数当渲染器。
判断标准
- build 超过 5 分钟、文章数百上千——ISR 可以把成本摊到请求里,不必每次都在 build 时打包付清。
- 每天 20+ 篇更新、编辑团队不大——ISR 或按需 revalidation 比 20 次重新部署省心。
- 内容完全不变(法务页、文档、归档帖)——SSG 更简单更便宜。
- 撞上 Vercel build 时长上限(Hobby 45 分钟,Pro 更高)——这是最响的 ISR 信号。
快速结论
文章数 500 以内、改动不频繁、build 快:SSG 赢。文章数 2000 以上或日更:ISR + 按需 revalidation 赢。中间地带两者都行,按团队流程选,别拿 benchmark 较劲。
该用 SSG 的真实信号
五条说明 SSG 就够了:
- build 3 分钟以内——为改个错字重新部署一点都不痛。
- 编辑会用 git,或者 CMS 保存时已经自动触发部署。
- 想要最无聊的生产:CDN 直发文件,零函数调用,没有意外。
- 回滚就是”把上一个部署 promote 回去”——瞬时、原子、不用清缓存。
- 托管账单应当大致等于一份 CDN 的成本。
Astro 默认 SSG,output: 'static'。Next.js 在有 generateStaticParams、没有动态 API 的路由上默认 SSG。
ISR 真正赚回成本的场景
三个具体例子:
- build 时间是瓶颈。 5000+ 文章、build 20 分钟、每次改错字都要等 20 分钟。ISR 只预生成最热门的 slug,其他懒生成:
// app/articles/[slug]/page.tsx
export const revalidate = 3600; // ISR:最多每小时再生成一次
export async function generateStaticParams() {
// 只预渲染 top 200,剩下的懒加载
return (await getTopArticles(200)).map(a => ({ slug: a.slug }));
}
- CMS webhook 触发按需 revalidation。 编辑在 Sanity / Contentful 里点发布,webhook 调
/api/revalidate,那一个 URL 几秒内重新生成,不用全站重新部署:
// app/api/revalidate/route.ts
import { revalidatePath } from 'next/cache';
import { NextRequest, NextResponse } from 'next/server';
export async function POST(req: NextRequest) {
const secret = req.nextUrl.searchParams.get('secret');
if (secret !== process.env.REVALIDATE_SECRET) {
return NextResponse.json({ ok: false }, { status: 401 });
}
const { slug } = await req.json();
revalidatePath(`/articles/${slug}/`);
return NextResponse.json({ ok: true, revalidated: slug });
}
- 按时间刷新局部内容。 正文不变,但”相关文章”模块要每周更新。把
revalidate = 604800设上,页面自己重新生成。
回滚方式不同
- SSG 回滚一键搞定——Vercel 把上一个 build promote 回去,所有页面原子切换。
- ISR 回滚麻烦点——上一版本部署里函数缓存可能还存着已经重新生成的旧版本。promote 后要
revalidatePath或revalidateTag,否则等 TTL 过。
容易踩的坑
- “保险起见”每页都设
revalidate = 60——你刚把首次冷请求之后的每次请求都变成函数调用了。账单涨、CDN 命中率掉。 - 用了 ISR 但没接按需 hook——编辑仍要等 revalidate 窗口才看得到自己改的。
- 忘了 ISR 需要部署 Node serverless 函数,不只是静态文件——影响成本模型和需要哪个 Vercel 套餐。
- 同一项目里 SSG 和 ISR 混着用,搞不清某页为什么显示旧内容——查那段路由的
export const revalidate。 - 把 Astro 的
output: 'hybrid'当”Astro ISR”——它更接近按路由 SSR。Astro 2026 还没有真正的 ISR,只有 Vercel adapter 提供的按需重新生成。
FAQ
- ISR 对 SEO 是不是比 SSG 差?: 不。两者给爬虫的都是预渲染 HTML。ISR 在重新部署后的第一次再生成可能稍慢,之后都是 CDN 速度。
- Astro 能用 ISR 吗?: 算半个。Astro 用 Vercel adapter 有按需渲染,但没有 Next.js 的 stale-while-revalidate 时间语义。Astro 内容站走 SSG 通常就够了。
- Vercel 的 Data Cache 是什么?: 那是按 fetch 的缓存,和 ISR 正交。两者能一起用:ISR 缓存整页渲染结果,Data Cache 缓存里面单个
fetch()。 - 再生成失败会怎样?: 旧页继续提供服务。你能在 Vercel 日志里看到错误,但用户看到的还是上一次正常版本——这正是设计意图。
- ISR 和
revalidateOnInterval一个意思吗?: 思路一样,框架叫法不同。Astro 和 SvelteKit 在 Vercel 上术语不同,缓存原语是同一个。