创见博客
Next.js的渲染策略SSR、SSG与ISG
七崽爱吃小饼干2026/01/18阅读 6专栏 React

Next.js 三大核心渲染策略:SSR、SSG、ISR

Next.js 中服务端渲染(SSR)、静态站点生成(SSG)、增量静态再生(ISR) 这三大核心渲染策略的详细讲解,这三个是 Next.js 最核心、最常用的渲染方式(官方正统分类,无争议),均属于「服务端参与的渲染」,区别于纯浏览器的客户端渲染(CSR)。


一、先统一核心基础:三个渲染策略的「共性」

  1. 三者最终给浏览器返回的都是 完整的 HTML 内容(首屏有真实内容,不是空白 div),完美解决 React 纯 CSR 的「首屏白屏、SEO 极差」问题;
  2. 三者的「数据请求/页面组件编译」都在 Node.js 服务端 执行(而非浏览器),前端只是做「接收HTML+水合激活交互」;
  3. 三者执行的最后一步都是「Hydration 水合」:浏览器拿到服务端生成的 HTML 后,加载对应的 JS 文件,将静态 DOM 节点「激活」为有交互能力的 React 组件,这一步是 Next.js 自动完成的。

二、一、静态站点生成 「SSG - Static Site Generation」

核心定义

页面的 HTML 内容,在项目「构建阶段(build 时)」一次性生成完毕,之后项目运行的所有阶段,不管多少用户访问、访问多少次,都复用这份提前生成好的静态 HTML 文件。

生成后是纯静态资源,可直接部署在 CDN 上,这是 Next.js 性能最优的渲染方式,没有之一。

核心特点

  1. 生成时机:仅在 npm run build / yarn build 构建时生成,构建完成后,HTML 内容永久固定;
  2. 访问速度:极致快!CDN 直接返回静态文件,无需服务端做任何计算,响应时间毫秒级;
  3. 数据更新:页面内容是「静态的」,如果后端数据变了,必须重新执行 build 构建,才能更新页面内容;
  4. 资源占用:服务端资源占用为 0,因为根本不需要服务端处理请求,所有请求都由 CDN 承接;
  5. 适用场景:内容不常变化、对访问速度和SEO要求极高 的页面,90%的业务场景首选。

典型适用场景

  • 博客/文档网站(比如掘金、知乎专栏、Next.js官网)
  • 产品介绍页、官网、营销落地页
  • 帮助中心、知识库、公告页
  • 电商商品分类页(非实时库存的)

代码实现

Next.js 13+ App Router(主流,推荐)

App Router 中,SSG是默认渲染策略,无需任何特殊标记,写组件+请求数据即可,Next.js 自动在构建时生成静态HTML。

tsx
// app/page.tsx (首页,默认SSG)
// 数据请求:直接写在组件顶层,Next.js自动在build时执行请求,生成静态HTML
async function getArticleList() {
  const res = await fetch('https://api.xxx.com/articles', {
    next: { revalidate: false } // 显式声明:永久静态,不重新验证(SSG标识)
  })
  return res.json()
}

export default async function Home() {
  const articles = await getArticleList()
  return (
    <div>
      <h1>我的博客(SSG静态生成)</h1>
      {articles.map(item => <p key={item.id}>{item.title}</p>)}
    </div>
  )
}

Next.js 12- Pages Route

通过约定式的 getStaticProps 方法实现 SSG,只要页面中导出这个方法,就会被识别为 SSG 页面:

tsx
// pages/index.tsx
export default function Home({ articles }) {
  return (
    <div>
      <h1>我的博客(SSG静态生成)</h1>
      {articles.map(item => <p key={item.id}>{item.title}</p>)}
    </div>
  )
}

// 核心:build时执行,获取数据并注入组件props
export async function getStaticProps() {
  const res = await fetch('https://api.xxx.com/articles')
  const articles = await res.json()
  return {
    props: { articles }, // 传给页面组件的数据
    revalidate: false,    // 关闭增量再生,纯SSG
  }
}

三、二、服务端渲染 「SSR - Server Side Rendering」

核心定义

页面的 HTML 内容,在「用户每次发起请求时」,由服务端实时生成。用户每访问一次页面,服务端就会重新执行「组件渲染+数据请求」,生成全新的 HTML 返回给浏览器。

没有提前构建的静态文件,每次请求都是一次全新的服务端计算,这是和 SSG 最核心的区别。

核心特点

  1. 生成时机:用户每次访问页面时,服务端实时生成 HTML,无提前构建;
  2. 访问速度:比 SSG 慢,比纯 CSR 快!因为需要服务端实时计算,响应时间取决于服务端性能和数据请求速度;
  3. 数据更新:实时性极强!后端数据变更后,用户刷新页面就能看到最新内容,无需重新构建;
  4. 资源占用:服务端资源占用较高,每一次用户请求都会消耗服务端的 CPU/内存,访问量越大,服务端压力越大;
  5. SEO友好:和 SSG 一样,返回完整 HTML,搜索引擎可以正常抓取内容;
  6. 核心优势:数据实时性,这是 SSR 存在的唯一核心价值。

典型适用场景

  • 数据实时变化的页面:股票行情、天气实时数据、体育赛事比分
  • 后台管理系统的首页数据看板(实时统计)
  • 电商商品详情页(需要实时显示库存、价格)
  • 社交平台的动态流(实时显示最新帖子/评论)

代码实现

Next.js 13+ App Router

App Router 中,通过给 fetch 添加 { cache: 'no-store' } 标记,即可声明为「SSR 模式」,表示不缓存、每次请求都重新获取数据+生成HTML:

tsx
// app/price/page.tsx (实时股票价格页面,SSR)
async function getStockPrice() {
  const res = await fetch('https://api.xxx.com/stock/price', {
    cache: 'no-store' // 核心标记:关闭缓存 → 触发SSR
  })
  return res.json()
}

export default async function StockPrice() {
  const price = await getStockPrice()
  return (
    <div>
      <h1>实时股票价格(SSR服务端渲染)</h1>
      <p>当前价格:{price.now}</p>
      <p>更新时间:{price.updateTime}</p>
    </div>
  )
}

Next.js 12- Pages Router

通过约定式的 getServerSideProps 方法实现 SSR,只要页面导出这个方法,就会被识别为 SSR 页面,每次请求都会执行这个方法:

tsx
// pages/price.tsx
export default function StockPrice({ price }) {
  return (
    <div>
      <h1>实时股票价格(SSR服务端渲染)</h1>
      <p>当前价格:{price.now}</p>
    </div>
  )
}

// 核心:每次请求时执行,实时获取数据
export async function getServerSideProps() {
  const res = await fetch('https://api.xxx.com/stock/price')
  const price = await res.json()
  return { props: { price } }
}

四、三、增量静态再生 「ISR - Incremental Static Regeneration

核心定义

ISR = SSG + 自动更新,是 Next.js 独创的「超集渲染策略」,结合了 SSG的极致性能 和 SSR的实时更新能力,是两者的完美折中方案,也是 Next.js 最核心的竞争力!

本质逻辑:页面在「构建阶段」按照 SSG 的方式生成静态 HTML 并缓存(走CDN),之后在指定的「过期时间」内,所有用户访问都复用这份静态文件;当超过过期时间后,有用户访问时,服务端会「后台静默重新生成」最新的 HTML 文件并更新缓存,后续用户访问就拿到新内容。

核心特点

  1. 生成时机:首次构建时生成静态HTML(同SSG),之后「按需增量更新」,无需全量重新build;
  2. 访问速度:极致快!99%的请求都是 CDN 返回静态缓存,和 SSG 速度一致;
  3. 数据更新:按需自动更新!无需手动触发 build,也无需每次请求都计算,兼顾「实时性」和「性能」;
  4. 核心机制 - 静默再生:当页面缓存过期后,第一个访问的用户 会触发服务端的「重新生成」,但这个用户会先拿到旧的缓存内容,不会等待生成过程;服务端在后台生成好新的 HTML 后,会更新缓存,后续所有用户 都能看到最新内容;
  5. 资源占用:极低!只有缓存过期时,服务端才会执行一次生成,其余请求全由 CDN 承接;
  6. 核心优势:鱼和熊掌兼得 —— SSG的性能 + SSR的实时性,解决了 SSG「更新麻烦」和 SSR「性能差、服务端压力大」的两大痛点。

典型适用场景(业务中最常用,优先级高于SSG/SSR)

这是 Next.js 最推荐的生产环境渲染方式,绝大多数业务页面都适用,比如:

  • 电商商品详情页(需要更新价格/库存,但不需要毫秒级实时)
  • 资讯/新闻页面(需要定时更新内容,比如每10分钟刷新一次)
  • 博客/自媒体(文章发布后自动更新,无需重新部署)
  • 排行榜/榜单页面(比如热榜、销量榜,定时更新)
  • 企业官网的动态板块(比如最新活动、产品更新)

代码实现

Next.js 13+ App Router

App Router 中,ISR 的实现极其简单:通过 fetch 的 next: { revalidate: 时间秒数 } 标记即可,这是ISR的核心标识,revalidate 就是「缓存过期时间」。

tsx
// app/article/[id]/page.tsx (博客详情页,ISR,每60秒更新一次)
async function getArticle(id: string) {
  const res = await fetch(`https://api.xxx.com/articles/${id}`, {
    next: { revalidate: 60 } // 核心标记:缓存60秒,60秒后自动静默再生 → ISR
  })
  return res.json()
}

// 动态路由页面,接收路由参数
export default async function Article({ params }) {
  const article = await getArticle(params.id)
  return (
    <div>
      <h1>{article.title}</h1>
      <div>{article.content}</div>
      <p>缓存过期时间:60秒后自动更新</p>
    </div>
  )
}

Next.js 12- Pages Router

Pages Router 中,ISR 是在 SSG的 getStaticProps 中添加 revalidate 属性实现的,本质是给SSG增加了自动更新能力:

tsx
// pages/article/[id].tsx
export default function Article({ article }) {
  return (
    <div>
      <h1>{article.title}</h1>
      <div>{article.content}</div>
    </div>
  )
}

// 1. getStaticPaths:build时生成指定id的静态页面(SSG)
export async function getStaticPaths() {
  const res = await fetch('https://api.xxx.com/articles')
  const articles = await res.json()
  const paths = articles.map(article => ({ params: { id: article.id.toString() } }))
  return { paths, fallback: 'blocking' }
}

// 2. getStaticProps + revalidate:核心ISR配置,缓存60秒
export async function getStaticProps({ params }) {
  const res = await fetch(`https://api.xxx.com/articles/${params.id}`)
  const article = await res.json()
  return {
    props: { article },
    revalidate: 60, // 关键:缓存60秒,过期后自动静默再生 → ISR
  }
}

五、三者核心区别对比

用一张表格清晰对比,所有核心差异一目了然,收藏这张表就够了:

特性维度SSG (静态站点生成)SSR (服务端渲染)ISR (增量静态再生)
HTML生成时机build构建时 一次性生成用户每次请求 实时生成build时生成 + 过期后静默增量更新
访问速度极致快(CDN直返)较慢(服务端实时计算)和SSG一致(CDN直返)
数据实时性最差(需重新build更新)最好(数据实时最新)优秀(按需更新,可控延迟)
服务端资源占用0占用(无服务端计算)极高(每次请求都计算)极低(仅过期时计算一次)
核心优势性能极致、部署简单、成本低数据绝对实时、无更新成本性能+实时性兼得,完美折中
核心缺点数据更新麻烦,需重新构建性能差、服务端压力大、成本高有短暂的数据延迟(可通过配置解决)

六、生产环境选型建议

这是我做Next.js项目的实战选型经验,99%的场景都适用,优先级从高到低:

1. 首选:ISR 增量静态再生

  • 适用:除了「数据需要毫秒级实时」和「纯静态永不更新」的所有场景;
  • 理由:兼顾性能和实时性,服务端压力小,部署成本低,几乎没有缺点,是Next.js的「最优解」。

2. 其次:SSG 静态站点生成

  • 适用:内容永久不变/极少变化的页面(比如官网、帮助文档、博客归档);
  • 理由:性能天花板,部署最简单,CDN即可承载所有流量,成本最低。

3. 最后:SSR 服务端渲染

  • 适用:必须实时展示最新数据的页面(比如股票行情、实时榜单、实时库存);
  • 理由:只有在「数据实时性」是第一优先级时才用,因为它的性能和资源占用都是短板。

七、混合使用三种策略

Next.js 完全支持在同一个项目中为不同路由混合使用 SSG、SSR、ISR 三种渲染策略,这也是 Next.js 灵活性的核心体现。

Next.js 的渲染策略是路由级别的配置,不同路由页面可以独立选择适合自己的渲染方式,框架会自动对每个路由做差异化处理,互不干扰。

  1. 路由隔离性:Next.js 的渲染策略是绑定到单个路由页面的,而非全局配置。每个路由页面的渲染逻辑、数据获取方式都是独立的。
  2. 约定式区分:无论是 App Router 还是 Pages Router,都是通过代码约定来标记当前路由的渲染策略,不同路由的标记互不影响。
  3. 构建/运行时差异化处理:
    • 标记为 SSG/ISR 的路由,会在 build 阶段生成静态 HTML 文件;
    • 标记为 SSR 的路由,不会在 build 阶段生成静态文件,而是在用户请求时实时计算;
    • 部署后,CDN 会缓存 SSG/ISR 路由的静态资源,SSR 路由则直接走服务端计算。

1.混合使用的实战案例(App Router 版本,Next.js 13+)

以一个电商项目为例,不同路由使用不同渲染策略:

tsx
// 1. 首页(app/page.tsx)- 用 ISR
// 原因:首页有活动banner、热门商品,需要定时更新,又要极致性能
async function getHomeData() {
  const res = await fetch('https://api.xxx.com/home', {
    next: { revalidate: 300 } // 5分钟更新一次 → ISR
  })
  return res.json()
}
export default async function Home() {
  const data = await getHomeData()
  return <div>{/* 首页内容 */}</div>
}

// 2. 商品分类页(app/category/[id]/page.tsx)- 用 SSG
// 原因:分类数据极少变化,纯静态展示,优先 CDN 性能
async function getCategory(id: string) {
  const res = await fetch(`https://api.xxx.com/category/${id}`, {
    next: { revalidate: false } // 永久静态 → SSG
  })
  return res.json()
}
export default async function Category({ params }) {
  const data = await getCategory(params.id)
  return <div>{/* 分类内容 */}</div>
}

// 3. 实时订单页(app/order/realtime/page.tsx)- 用 SSR
// 原因:订单数据需要毫秒级实时更新,必须每次请求都获取最新数据
async function getRealtimeOrder() {
  const res = await fetch('https://api.xxx.com/order/realtime', {
    cache: 'no-store' // 不缓存,每次请求实时获取 → SSR
  })
  return res.json()
}
export default async function RealtimeOrder() {
  const data = await getRealtimeOrder()
  return <div>{/* 实时订单内容 */}</div>
}

2.混合使用的注意事项

  1. 数据获取的一致性:不同渲染策略的路由,数据获取的运行环境都是服务端(App Router 中顶层 async 函数、Pages Router 中 getStaticProps/getServerSideProps),可以复用相同的 API 请求函数,只需调整缓存配置。
  2. 部署兼容:混合渲染的项目部署时,需要确保平台支持 Next.js 的服务端能力(比如 Vercel、Netlify、阿里云函数计算),纯静态托管平台(如 GitHub Pages)无法运行 SSR 路由。
  3. 缓存策略统一:建议为 ISR 路由设置合理的 revalidate 时间,避免不同页面的更新频率差异过大,导致用户看到的数据不一致。
  4. 动态路由适配:动态路由(如 [id])在 SSG/ISR 模式下,需要通过 generateStaticParams(App Router)或 getStaticPaths(Pages Router)预先生成部分静态页面,未预生成的路径可配置 fallback 策略。

3.混合使用的核心优势

  • 性能与实时性兼顾:高频访问、变化少的页面用 SSG/ISR 走 CDN,低频访问、实时性要求高的页面用 SSR,最大化优化用户体验和服务端资源。
  • 开发成本低:无需拆分项目,一个 Next.js 项目即可覆盖所有业务场景的渲染需求。

总结

  1. SSG 是「一次构建,永久复用」,性能最好,实时性最差;
  2. SSR 是「每次请求,实时生成」,实时性最好,性能最差;
  3. ISR 是「SSG的升级款」,Next.js 独创杀手锏,性能≈SSG,实时性≈SSR,是业务首选;
  4. 三者的核心差异,本质只有一个:HTML 生成的时机和更新的方式。
评论
0/100