静态站和 SSR 站如何选

静态和 SSR 在 Next.js 项目里看起来差不多,直到你扩容、上线、看账单。2026 年内容站怎么正确选,本文讲清楚。

静态 vs SSR 这一个决定,悄悄决定了你的托管成本、首字节时间、Core Web Vitals,以及半夜被 500 报警叫醒的频率。内容站的答案几乎总是”静态为主,关键点撒点动态”。本文教你怎么真的判断。

问题背景

现代 Next.js(App Router)边界模糊:一个 route 可以是静态、ISR 缓存、动态 SSR、streaming。这种灵活性是优点,但人们经常不小心默认走了 SSR——忘了 generateStaticParams,或者哪里调了 cookies()。内容站这就是自己制造的倒退。

三种模式在代码里长什么样

Next.js App Router,强制静态——这是大多数文章页应该有的样子:

// app/articles/[slug]/page.tsx
export const dynamic = 'force-static';
export const revalidate = false;

export async function generateStaticParams() {
  return getAllSlugs().map((slug) => ({ slug }));
}

export default async function Article({ params }: { params: { slug: string } }) {
  const post = await getPost(params.slug);
  return <Markdown source={post.body} />;
}

ISR——结构一样,但内容会按周期刷新而不需要重新部署:

export const revalidate = 300;  // 最多每 5 分钟重渲一次

SSR——只在页面真的依赖请求时才用:

export const dynamic = 'force-dynamic';
// 隐含使用 cookies()/headers();每次请求都打到服务器

Astro 默认就是静态,需要 SSR 的路由再按需开启:

// astro.config.mjs
import { defineConfig } from 'astro/config';
export default defineConfig({
  output: 'static',                                  // 全局默认
  // output: 'hybrid',                               // 按路由开启 SSR
  // adapter: import('@astrojs/node').default(),     // 真需要时才装 adapter
});

判断标准

  • 同一篇文章所有人看到一样——静态。
  • 内容因人 / 因地区而异(登录态 dashboard、地理优惠)——SSR。
  • 想要 CDN 便宜托管、稳定低延迟——静态。
  • 每次渲染都要拉最新价格 / 库存 / 比分——SSR 或短窗口 ISR。
  • 部署到 Cloudflare / Firebase / S3 / GitHub Pages——静态(这些平台不会按请求跑 Node)。

快速结论

内容站默认静态。只有页面真的依赖请求级数据再用 SSR。ISR(每 N 秒重新生成)是”基本静态、偶尔更新”的中间档,多数人想用 SSR 时其实想要的是 ISR。

实操步骤

  1. 列出每条 route,标成:静态、ISR(带 revalidate 窗口)、SSR、客户端渲染。
  2. 每个标 SSR 的问一句:“同一分钟两个匿名访客之间有什么变化?“没变化就该静态。
  3. 每个 ISR 选 revalidate 窗口。多数博客 60s 够,价格页可能 300s,几乎没有真需要 1s 的。
  4. Next.js App Router 里检查 route 有没有意外变动态,要确定静态就显式写 dynamic = 'force-static'
  5. RSC fetch 显式 cache: 'force-cache'next: { revalidate: N },别留隐式。
  6. 部署后看 build 输出——Next.js 会标 Static / SSG / Dynamic,逐条审。
  7. 对部署后的静态页跑 Lighthouse,TTFB 和 LCP 干净就说明选对了。

容易踩的坑

  • 不小心变动态——layout 里一个 cookies()headers(),整个子树都变动态。
  • ISR revalidate 设太狠(每 10 秒),为日更内容烧函数调用。
  • “以防万一”选 SSR——过早灵活和过早优化一样,立刻就为冷启动和账单付费。
  • 需要 CDN 缓存保性能承诺的 route 没显式 dynamic = 'force-static'
  • 在不跑 Node 的托管上(Cloudflare Pages 不带 Workers、纯 S3、GitHub Pages)试图 SSR,然后不明白为什么不行。

这篇适合谁

独立内容站——博客、文档、垂直目录、课程站——95% 以上流量看到同一份 HTML。

这篇不适合谁

有登录墙、个性化流、内容跟访客绑定(auth / geo / A/B)的 App,真需要 SSR 或客户端渲染。

FAQ

  • ISR 是不是就是缓存 SSR?: 效果上是。Next.js 在 revalidate 窗口过期后第一次请求时构建页面,然后给后续所有人发缓存 HTML,直到下次过期。
  • 用了 CMS 还能静态吗?: 能。build 时从 Contentful / Sanity / Notion 拉数据仍然是静态。发布时 webhook 触发重新构建,两全其美。
  • 搜索怎么办?: 客户端搜索基于静态 JSON 索引,几千篇文章以内的内容站都够用。除非真要服务端大规模过滤再走 SSR 搜索。
  • 一个 Next.js 项目能静态和 SSR 混用吗?: 能,这就是 App Router 的核心——每个 route 自选策略。

相关阅读

标签: #独立开发 #Next.js #建站策划 #对比 #Core Web Vitals