创见博客
Next.js的工作流程
七崽爱吃小饼干2026/01/18阅读 0专栏 React

Next.js 工作流程(SSR 核心场景)

本文基于 React 服务端渲染(SSR)核心逻辑,以 Next.js 12 及之前的 Pages Router(带 getServerSideProps)为典型场景,同时补充 App Router 流式渲染特性,覆盖请求接收 → 服务端处理 → 客户端响应 → 水合交互全链路。

一、 整体流程概览

用户请求 → 服务端路由解析与数据预取 → 服务端组件渲染生成 HTML → 服务端返回资源包 → 浏览器首屏渲染 → 客户端 JS 下载与水合 → 客户端接管交互

二、 分步详细拆解

1. 用户发起请求

用户在浏览器输入 URL 或点击页面内链接,向 Next.js 服务器(基于 Node.js)发送 HTTP 请求,请求携带 URL 路径、Cookie、请求头等信息。

2. 服务端接收请求与路由解析

  • Next.js 服务器监听端口并接收请求,通过内置路由系统匹配对应页面组件:
    • Pages Router:根据 pages 目录结构匹配路由(如 pages/user/[id].js 匹配 /user/1)。
    • App Router:根据 app 目录下的文件夹结构和 page.js 文件匹配路由。
  • 路由匹配成功后,判断页面类型:若为 SSR 页面(Pages Router 导出 getServerSideProps,App Router 使用 async 组件或 generateServerSideProps),进入服务端数据预取与渲染流程;若为静态生成(SSG)页面,直接返回预构建的 HTML。

3. 服务端数据预取(SSR 核心步骤)

该步骤仅在服务端执行,目的是获取页面渲染所需的完整数据,避免客户端二次请求导致首屏延迟:

  • Pages Router:执行页面导出的 getServerSideProps 方法,该方法接收 context 参数(包含路由参数、请求头、Cookie 等),可发起 API 请求、查询数据库获取数据,最终返回 { props: {...} },数据会作为组件属性传入页面组件。
  • App Router:在 page.js 或 layout.js 中编写 async 函数直接获取数据,或使用 generateServerSideProps 方法,数据通过 props 传递给组件。
  • 关键特性:数据预取逻辑不会在客户端执行,完全隔离在服务端环境。

4. 服务端组件渲染生成 HTML

  • Next.js 调用 React 服务端渲染引擎(ReactDOMServer.renderToString 或 renderToPipeableStream),将页面组件与预取数据结合,生成带完整业务内容的静态 DOM 字符串。
  • 组件渲染时的 Hooks 执行规则:
    • 执行 useState useMemo useContext 等无副作用 Hooks,用于计算组件状态与渲染内容。
    • 完全跳过 useEffect useLayoutEffect,这两个 Hooks 仅在客户端水合阶段执行。
  • App Router 流式渲染差异:服务端不一次性生成完整 HTML,而是分块返回 HTML 片段,浏览器可边接收、边渲染,提升首屏加载速度。

5. 服务端打包并返回资源

服务端将以下资源整合为 HTTP 响应,返回给浏览器:

  1. 完整 HTML 字符串:包含基础骨架(<html> <head> <body>)、组件渲染的静态 DOM(嵌入 <body>)、内联的初始数据(挂载到全局变量 window.__NEXT_DATA__,包含预取数据、路由信息等)。
  2. 客户端 JS 脚本链接:包括 Next.js 运行时、React 核心库、页面专属组件逻辑代码,通过 <script> 标签引入。
  3. 静态资源链接:CSS 文件(通过 <link> 引入)、图片/字体等静态资源的 CDN 链接,支持代码分割与缓存优化。
  4. 辅助资源(可选):polyfill 脚本(兼容低版本浏览器)、埋点/监控脚本等。
  • 核心注意点:不传输 React Fiber 树,Fiber 树是服务端渲染的临时内部数据结构,生成 HTML 后即被销毁。

6. 浏览器首屏渲染

浏览器接收响应后,立即解析 HTML 并渲染 <body> 中的静态 DOM,用户无需等待 JS 下载即可看到页面内容,这是 SSR 提升首屏体验的核心优势。同时,浏览器并行下载 HTML 中引用的 JS、CSS、图片等资源。

7. 客户端 JS 下载与水合(Hydration)

  • JS 脚本下载完成后执行,Next.js 启动客户端水合流程,核心目标是将静态 DOM 转为可交互的 React 组件实例。
  • 水合过程步骤:
    1. 读取 window.__NEXT_DATA__ 中的初始数据,避免重复请求。
    2. React 重新执行页面组件代码,构建客户端虚拟 DOM 与 Fiber 树。
    3. 对比客户端虚拟 DOM 与页面静态 DOM 的结构一致性,确保无差异后,为 DOM 节点绑定事件监听(如点击、输入)。
    4. 执行 useEffect useLayoutEffect 钩子,处理客户端副作用(如操作 DOM、发起非首屏数据请求、初始化第三方 SDK)。

8. 客户端接管后续交互

水合完成后,页面进入完全可交互状态,后续操作由客户端 React 接管:

  • 路由跳转:使用 Next.js 内置的 next/link 或 next/router 实现客户端路由切换,无需重新请求服务端(除非跳转至新的 SSR 页面)。
  • 状态更新:组件的 setState useReducer 等操作触发客户端重新渲染,遵循 React 客户端渲染逻辑。
  • 数据更新:非首屏数据请求(如分页加载、筛选条件变更)通过 useEffect 在客户端发起,更新页面内容。

三、 关键特性补充

  1. 环境隔离:服务端代码(如 getServerSideProps)与客户端代码完全隔离,服务端可访问 Node.js API,客户端可访问浏览器 API(需在 useEffect 中使用)。
  2. 缓存策略:支持多种缓存方案,如 SSG 页面的构建时缓存、ISR(增量静态再生)的按需缓存、SSR 页面的请求级缓存,可通过配置灵活控制。
  3. 代码分割:Next.js 自动对 JS、CSS 进行代码分割,只加载当前页面所需资源,减少首屏加载体积。

四、 不同渲染模式的流程差异

渲染模式核心差异点适用场景
SSR(服务端渲染)每次请求都执行数据预取与组件渲染动态数据页面(如用户中心、实时榜单)
SSG(静态生成)构建时完成数据预取与 HTML 生成,请求时直接返回静态内容页面(如博客、文档、营销页)
ISR(增量静态再生)基于 SSG,定时或按需重新生成页面半静态半动态页面(如商品详情页)
客户端渲染服务端返回空 HTML,客户端 JS 加载后获取数据并渲染后台管理系统等对 SEO 无要求的页面
评论
0/100