后端转全栈之Next.js渲染(CSR/SSR/SSG/ISR)

97 阅读6分钟

Next.js渲染(CSR/SSR/SSG/ISR)

本文概括

本文介绍了 Next.js 的主要渲染方式,包括 CSR、SSR、SSG、ISR,以及 RSC 和 Suspense。

  • CSR:客户端渲染,适合交互密集的页面。
  • SSR:服务端渲染,首屏快,SEO 友好,适合动态内容。
  • SSG:构建时生成静态页面,性能高,适合不常更新的内容。
  • ISR:在 SSG 基础上定期刷新页面,兼顾性能与动态性。
  • RSC:服务端组件,减小客户端包,支持直接访问后端数据。
  • Suspense:延迟渲染和流式渲染,可显示 fallback,优化首屏体验。

渲染方式

CSR(Client-Side Rendering 客户端渲染)

CSR(Client-Side Rendering) :页面在浏览器端渲染,服务器只返回一个空 HTML 和 JS 脚本,浏览器下载并执行 JS 后生成内容,适合交互密集的单页应用,但首屏渲染慢且 SEO 不友好。

在 App Router 中使用

  • 在组件文件顶部加上 'use client' 声明,使组件成为 Client Component
  • 页面初始只返回框架 HTML + JS,数据通过 useEffect 或 fetch 在客户端请求并渲染。

特点

  • 首屏加载慢,需要等待 JS 执行。
  • SEO 不佳,初始 HTML 内容几乎为空。
  • 适合高度交互或用户个性化的页面(如 Dashboard、后台管理系统)。
  • 可以使用 React Hooks(如 useStateuseEffect)和浏览器 API。

SSR(Server-Side Rendering 服务端渲染)

SSR(Server-Side Rendering) :每次请求时,服务器运行 React 组件生成完整 HTML 并返回浏览器,首屏渲染快且对 SEO 友好,适合内容需要实时更新的页面,但服务器压力较大。

在 App Router 中使用

  • 默认组件为 Server Component,在服务器端生成 HTML。
  • 可以在服务端获取数据并直接渲染页面。

特点

  • 每次请求都在服务器生成完整 HTML,无需等待 JS 执行即可显示,SEO 友好。
  • 适合动态内容页面,如库存、价格或用户相关信息。
  • 性能成本较高,每个请求都要渲染 HTML。
  • 限制:Server Component 不能直接使用 CSR 的 Hook(如 useStateuseEffect),但可以包含 Client Component。

SSG(Static Site Generation 静态站点生成)

SSG(Static Site Generation) :在构建阶段生成静态 HTML,所有请求直接返回静态页面,性能极高且 SEO 友好,适合内容不经常变动的页面,如博客或文档,但更新需要重新构建。

在 App Router 中使用

  • 默认 fetch 为静态缓存(cache: 'force-cache'),即 构建时生成 HTML 并缓存
  • 动态路由可配合 generateStaticParams 生成静态路径。

特点

  • 页面直接作为静态文件部署,可通过 CDN 高速分发,首屏渲染快。
  • 服务器压力低,性能最佳。
  • 内容更新需要重新构建。
  • 适合博客、文档、营销页等静态内容页面。

ISR(Incremental Static Regeneration 增量静态再生)

ISR(Incremental Static Regeneration) :在 SSG 基础上允许增量更新,页面首次请求返回静态内容,后台按设定时间重新生成 HTML 更新缓存,兼顾性能和动态性,适合需要定期更新的静态内容。

在 App Router 中使用

  • 在 fetch 或 getStaticProps 中设置 revalidate 时间,例如 revalidate: 10 表示页面每 10 秒自动更新一次。
  • 可结合动态路由和 generateStaticParams 使用,实现增量生成静态页面。

特点

  • 页面性能接近 SSG,首屏渲染快,可通过 CDN 分发。
  • 支持定期更新,无需重新构建整个站点。
  • 适合内容定期更新但不需要每次请求都动态生成的页面,如新闻列表、电商商品页。

RSC( React Server Component)

RSC 是 React 推出的服务端组件机制,允许在服务端渲染组件,并将渲染后的数据传输到客户端,而不是把整个组件打包到客户端。

  • 数据请求在服务端完成,客户端不需要知道数据获取过程。
  • 服务端组件生成的 HTML 并不直接可交互,需要客户端 JS 下载并水合(Hydration)后才能交互。

RSC与SSR的区别如下:

特性SSRRSC
渲染粒度页面级组件级
JS bundle服务端渲染的组件会被打包到客户端服务端组件代码不会打包到客户端
客户端状态页面刷新会丢失客户端状态保持,RSC可以多次获取数据而不刷新页面
数据获取必须在组件渲染前完成直接在服务端组件中获取数据,组件代码不会暴露到客户端
水合 (Hydration)整个页面选择性水合,客户端只水合需要交互的部分

特点:

  • 减小客户端 bundle 大小:服务端组件不打包到客户端,只传输渲染后的数据(RSC Payload)。
  • 直接访问后端资源:服务端组件中可以直接访问数据库、文件系统或 API,无需通过客户端请求。
  • 不能使用客户端 Hook:服务端组件不支持 useStateuseEffect 等,只能用服务端逻辑。
  • 可组合客户端组件:服务端组件可以导入客户端组件实现交互;客户端组件不能导入服务端组件。

渲染流程:

  • 服务端渲染 RSC 组件,生成 RSC Payload(包含渲染后的 HTML、数据和样式)。
  • 发送到客户端,客户端根据 RSC Payload 重建 React 树。
  • 客户端部分交互通过客户端组件实现,不影响服务端组件的数据。

缺点对比:

缺点SSRRSC
数据获取必须在组件渲染前完成可以分块获取,按需加载
客户端包大小组件全部打包到客户端服务端组件不打包,减小 bundle
水合时间必须等待整页水合可选择性水合,客户端只水合交互组件
页面刷新每次刷新页面都会重新渲染客户端状态可以保留,RSC 可重复请求数据而不刷新

使用方式:

  • 默认组件是 服务端组件,顶部不需要加 'use server'
  • 需要交互的组件加 'use client',导入的模块及子组件都会打包到客户端。
  • 服务器组件中可以直接导入客户端组件;客户端组件中不能导入服务器组件。

Suspense

Suspense 是 React 的延迟渲染机制,允许组件在等待数据或资源时显示 fallback(loading 状态),并在数据准备好后再渲染真实内容。在 Next.js 中,Suspense 可以与 RSC 流式渲染(Streaming SSR)  配合使用,实现部分水合和流式页面渲染。特点如下:

  • 延迟渲染:数据未准备好时,显示 fallback,页面不会阻塞其他部分渲染。
  • 流式渲染 (Streaming SSR) :页面分块渲染,每个组件准备好后立即发送到客户端,提升首屏渲染速度。
  • 选择性水合:只对需要交互的组件进行水合,减少客户端 JS 执行量。
  • SEO 友好:最终 HTML 会包含全部内容,搜索引擎可抓取。

参考链接:nextjs.org/docs/app/ge…

流式渲染 (Streaming)

  • Next.js 将页面拆分成多个块 (chunks),每块准备好就发送给客户端。
  • 客户端收到块后立即渲染,不必等整个页面渲染完再显示。
  • 传统 SSR 是串行渲染,Streaming SSR 是并行渲染,提高首屏可见速度。
  • 页面级别使用loading.tsx,组件级别使用Suspense