01 · NOTES / WebGIS 开发
第 25 节 · 渲染策略全解(SSG / ISR / SSR / 流式)
2026 年 9 月 1 日
第 25 节 · 渲染策略全解(SSG / ISR / SSR / 流式)
📌 版本信息:Next.js 15.x(2026-08-29 核对) 📚 来源:Next.js · Rendering | generateStaticParams | revalidate 📖 定位:阶段二精读——把第 19 节的策略地图落到"每条路由怎么配"。
一、这一节的目标
- 掌握 App Router 里每条路由的渲染策略判定规则
- 精通 SSG 的实现(generateStaticParams)与 ISR 的实现(revalidate)
- 理解静态/动态的"混合页"(同页两种组件)
- 理解流式渲染与 loading.js 的关系
- 会用 build 输出与 API 判定"这条路由到底是什么"
二、策略判定:路由级、由代码决定
App Router 的策略不是全局开关,而是每条路由由其代码形态自动判定:
| 代码形态 | 判定 | 策略 |
|---|---|---|
| 无动态函数、无动态数据 | 构建时渲染 | SSG |
generateStaticParams + 已知参数 |
构建时逐参数生成 | SSG(动态段静态化) |
数据带 revalidate |
SSG + 定时再生 | ISR |
用了 cookies()/headers()/searchParams 或 cache: '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 |
六、自测题
- 一条路由是 SSG 还是 SSR 由什么决定?build 输出怎么看?
- generateStaticParams 的返回值形状?
- 页面级 revalidate 和数据级 revalidate 的粒度差异?
- "SSG 页面上为什么能有点赞按钮"?
- 流式渲染解决什么问题?loading.js 的底层机制?
参考答案
- 由该段代码形态决定(动态 API/数据源有无);build 输出路由表:● 静态、ƒ 动态。
[{ slug: 'a' }, { slug: 'b' }]——与动态段参数名对应的对象数组。- 页面级:整段按周期再生;数据级:单个 fetch 各自缓存/再生,粒度更细可混用。
- 页面骨架是 SSG,点赞按钮是客户端岛(浏览器水合后交互)——服务端/客户端组件混合页。
- 慢数据不拖累整体响应,骨架先到内容后补;底层是 Suspense 边界(loading.js 自动包裹该段)。
七、下一步
策略会配 → 第 26 节:缓存体系全解,Next 最容易踩坑的部分一次讲清。
TAGSweb