返回笔记列表
01 · NOTES / WebGIS 开发

第 25 节 · 渲染策略全解(SSG / ISR / SSR / 流式)

2026 年 9 月 1 日

第 25 节 · 渲染策略全解(SSG / ISR / SSR / 流式)

📌 版本信息:Next.js 15.x(2026-08-29 核对) 📚 来源:Next.js · RenderinggenerateStaticParamsrevalidate 📖 定位:阶段二精读——把第 19 节的策略地图落到"每条路由怎么配"。

一、这一节的目标

  1. 掌握 App Router 里每条路由的渲染策略判定规则
  2. 精通 SSG 的实现(generateStaticParams)与 ISR 的实现(revalidate)
  3. 理解静态/动态的"混合页"(同页两种组件)
  4. 理解流式渲染与 loading.js 的关系
  5. 会用 build 输出与 API 判定"这条路由到底是什么"

二、策略判定:路由级、由代码决定

App Router 的策略不是全局开关,而是每条路由由其代码形态自动判定

代码形态 判定 策略
无动态函数、无动态数据 构建时渲染 SSG
generateStaticParams + 已知参数 构建时逐参数生成 SSG(动态段静态化)
数据带 revalidate SSG + 定时再生 ISR
用了 cookies()/headers()/searchParamscache: 'no-store' 数据 每请求渲染 SSR(动态)
// SSG 动态段静态化(第 22 节练习做过):
export async function generateStaticParams() {
  const posts = await getPosts();
  return posts.map((p) => ({ slug: p.slug }));   // 每个值生成一个静态页
}

// ISR:页面级的时间再生(写在该段 page/layout):
export const revalidate = 3600;                  // 每小时后台再生一次

// 也可以只在数据请求上 revalidate(更细粒度,第 26 节缓存体系的主角)

build 输出判读(必会)npm run build 后的路由表,符号含义—— (SSG,静态,圆点实心)|ƒ(SSR/动态,函数符号)。上线前看一眼这张表,就知道了每条路由的真实行为。


三、混合页:同页两种组件(这很常见)

一页之内:服务端组件部分决定页面骨架的渲染时机,客户端岛在浏览器水合。典型:博客详情页 = SSG 正文(服务端)+ 点赞按钮(客户端岛,第 23 节)。所以"这条路由是 SSG"描述的是服务端骨架;岛上的交互照常动态。理解这一点,"静态页怎么会有按钮"的困惑即消。


四、流式渲染(Streaming)

loading.js 的底层:Next 把该段包进 Suspense 边界——服务器先发送布局与骨架,页面数据就绪后再把内容"流"过去补上。好处:整体 TTFB 提前(用户先看到框架),慢数据不拖累快数据。

// 更细粒度的手动流式(阶段二认知级):
import { Suspense } from 'react';
export default function Page() {
  return (
    <>
      <h1>城市报告</h1>                          {/* 立即出现 */}
      <Suspense fallback={<p>统计计算中…</p>}>
        <SlowStats />                            {/* 慢组件单独流式补上 */}
      </Suspense>
    </>
  );
}
// async 组件 <SlowStats /> 可以直接作为 Suspense 的孩子(服务端组件特性)

五、C-03c 的策略表(学以致用)

页面 策略 实现
文章列表 SSG/ISR 数据 revalidate 300
文章详情 SSG generateStaticParams 列出全部 slug
归档/标签页 ISR revalidate
搜索结果 CSR 客户端组件 + fuse.js 本地索引
后台 /admin CSR + 动态 登录态、实时数据 no-store

六、自测题

  1. 一条路由是 SSG 还是 SSR 由什么决定?build 输出怎么看?
  2. generateStaticParams 的返回值形状?
  3. 页面级 revalidate 和数据级 revalidate 的粒度差异?
  4. "SSG 页面上为什么能有点赞按钮"?
  5. 流式渲染解决什么问题?loading.js 的底层机制?

参考答案

  1. 由该段代码形态决定(动态 API/数据源有无);build 输出路由表:● 静态、ƒ 动态。
  2. [{ slug: 'a' }, { slug: 'b' }]——与动态段参数名对应的对象数组。
  3. 页面级:整段按周期再生;数据级:单个 fetch 各自缓存/再生,粒度更细可混用。
  4. 页面骨架是 SSG,点赞按钮是客户端岛(浏览器水合后交互)——服务端/客户端组件混合页。
  5. 慢数据不拖累整体响应,骨架先到内容后补;底层是 Suspense 边界(loading.js 自动包裹该段)。

七、下一步

策略会配 → 第 26 节:缓存体系全解,Next 最容易踩坑的部分一次讲清。

TAGSweb