菜单

服务器端渲染

相关源文件

React 中的服务器端渲染 (SSR) 允许在服务器上渲染 React 组件并将 HTML 发送到客户端,在那里它可以被“注水”成一个完全交互式的应用程序。本文档解释了 React 的 SSR 架构、实现细节和关键概念。

有关服务器组件(一项补充但不同的技术)的信息,请参阅React 服务器组件

概述

React 的服务器端渲染实现包含两个主要子系统:

  1. Fizz - 用于输出 HTML 的流式服务器渲染器
  2. 注水(Hydration) - 将事件监听器附加到服务器渲染的 HTML 的客户端过程

这些系统协同工作,提供无缝体验:首先向用户提供快速的静态 HTML 内容,然后在 JavaScript 加载后“注水”该内容,使其具有交互性。

来源

使用 Fizz 进行服务器渲染

Fizz 是 React 的流式服务器渲染器,可逐步生成 HTML。与之前的实现不同,Fizz 围绕流式传输设计,允许浏览器逐步接收和处理 HTML,而不是等待整个页面渲染完成。

架构

Fizz 架构基于以下核心概念构建:

  1. 流式模型 - 分块逐步渲染 HTML
  2. Suspense 集成 - 支持用于异步渲染的 Suspense 边界
  3. 渐进式注水 - 允许页面部分独立注水

来源

关键组件

请求处理

当你启动服务器渲染时,React 会创建一个 Request 对象,该对象维护渲染过程的状态

来源

分段和边界管理

Fizz 将渲染输出组织成段,并对 Suspense 边界进行特殊处理

  • 分段(Segments) 代表 HTML 内容的部分
  • Suspense 边界 允许 UI 的某些部分在异步操作完成时“暂停”
  • 当一个组件在 Suspense 边界内部暂停时,Fizz 会先渲染回退内容,然后流式传输解析后的内容

来源

水合作用

服务器渲染 HTML 后,客户端需要通过附加事件监听器并将 React 组件树与现有 DOM 进行协调来“注水”它。这个过程由 React 的注水系统处理。

注水过程

来源

选择性注水

React 支持选择性注水,这意味着它可以优先对用户正在交互的 UI 部分进行注水。这通过确保应用程序最相关的部分首先变得交互式来提高感知性能。

选择性注水的关键要素包括:

  1. 渐进式注水 - 应用程序的部分可以独立注水
  2. Suspense 边界注水 - Suspense 边界可以独立注水
  3. 基于优先级的注水 - 用户交互可以提升注水优先级

来源

注水不匹配和错误恢复

注水要求客户端渲染的树与服务器上渲染的树完全匹配。当出现不匹配时,React 具有恢复机制:

  1. 客户端渲染回退 - 当注水无法与服务器输出匹配时,React 可以回退到客户端渲染
  2. 错误边界 - 可以捕获和处理组件树中的错误
  3. 警告系统 - 用于注水不匹配的开发警告

React 通过以下方式处理不匹配:

  1. 在开发模式下对不匹配发出警告
  2. 尝试通过从不匹配节点进行客户端渲染来恢复
  3. 在可能的情况下继续注水同级节点

来源

核心 API

React 提供了多种用于服务器渲染和注水的 API

服务器渲染 API

API描述
renderToPipeableStream()react-dom/server渲染为支持渐进式流的 Node.js 可管道流
renderToReadableStream()react-dom/server渲染为适用于浏览器环境的 Web Streams 可读流
renderToString()react-dom/server同步渲染为字符串(旧版,非流式)
renderToStaticMarkup()react-dom/server类似于 renderToString 但没有 React 特有的属性

客户端注水 API

API描述
hydrateRoot()react-dom/client从服务器渲染的 HTML 创建 React 根并注水它

示例流程

典型的服务器端渲染和注水流程如下所示:

  1. 服务器:使用 renderToPipeableStream 将 React 组件渲染为 HTML 流
  2. 服务器:将 HTML 发送给客户端,包括必要的脚本
  3. 客户端:最初显示非交互式 HTML
  4. 客户端:JavaScript 加载后,调用 hydrateRoot 使内容具有交互性

来源

Suspense 集成

Suspense 是 React SSR 策略的关键组成部分,它支持服务器端和客户端的异步渲染。

服务器端 Suspense 特性

Suspense 的服务器端实现允许:

  1. 渐进式 HTML 流式传输 - Suspense 边界允许服务器在页面部分准备就绪时进行流式传输
  2. 优先级内容 - 关键 UI 可以优先发送,次要内容稍后流式传输
  3. 占位符流式传输 - 在等待暂停内容时立即发送回退内容

来源

性能考量

服务器端渲染通过更快地向用户展示内容来提高感知性能,但伴随着权衡:

  1. 首字节时间 (TTFB) - SSR 可能会增加 TTFB,因为服务器必须在发送第一个字节之前渲染内容
  2. 可交互时间 (TTI) - 在注水完成之前,内容可见和可交互之间存在一个间隙
  3. 服务器负载 - 在服务器上渲染会增加 CPU 使用率

优化

React 的 SSR 实现包含多项优化:

  1. 渐进式流式传输 - 在内容可用时立即发送,而不是等待所有内容就绪
  2. 选择性注水 - 优先注水用户正在交互的页面部分
  3. 资源提示 - 预加载必要的资源以加快注水速度
  4. Suspense 边界 - 允许定义哪些内容是关键的,哪些可以稍后加载

来源

错误处理

React 为服务器渲染提供了强大的错误处理机制

服务器端错误

当服务器渲染期间发生错误时:

  1. 错误边界 - 可以捕获组件树中的错误
  2. onError 回调 - 可以提供给服务器渲染 API 以处理错误
  3. 回退到客户端渲染 - 如果服务器渲染失败,客户端可以尝试渲染

注水错误

在注水过程中,不匹配或错误通过以下方式处理:

  1. 开发模式警告 - 在开发过程中提供详细警告以帮助识别问题
  2. 客户端渲染回退 - 当注水失败时,React 可以丢弃服务器 HTML 并在客户端渲染
  3. 错误边界 - 可以捕获注水过程中的错误

来源

结论

React 的服务器端渲染系统为交付快速、交互式 Web 应用程序提供了强大的框架。Fizz 的流式架构,结合 Suspense 集成和渐进式注水,使开发人员能够平衡性能和交互性。

了解这些系统有助于你优化 React 应用程序,从而改善用户体验,特别是对于连接较慢或设备性能较低的用户。