React 中的服务器端渲染 (SSR) 允许在服务器上渲染 React 组件并将 HTML 发送到客户端,在那里它可以被“注水”成一个完全交互式的应用程序。本文档解释了 React 的 SSR 架构、实现细节和关键概念。
有关服务器组件(一项补充但不同的技术)的信息,请参阅React 服务器组件。
React 的服务器端渲染实现包含两个主要子系统:
这些系统协同工作,提供无缝体验:首先向用户提供快速的静态 HTML 内容,然后在 JavaScript 加载后“注水”该内容,使其具有交互性。
来源
Fizz 是 React 的流式服务器渲染器,可逐步生成 HTML。与之前的实现不同,Fizz 围绕流式传输设计,允许浏览器逐步接收和处理 HTML,而不是等待整个页面渲染完成。
Fizz 架构基于以下核心概念构建:
来源
当你启动服务器渲染时,React 会创建一个 Request 对象,该对象维护渲染过程的状态
来源
Fizz 将渲染输出组织成段,并对 Suspense 边界进行特殊处理
来源
服务器渲染 HTML 后,客户端需要通过附加事件监听器并将 React 组件树与现有 DOM 进行协调来“注水”它。这个过程由 React 的注水系统处理。
来源
React 支持选择性注水,这意味着它可以优先对用户正在交互的 UI 部分进行注水。这通过确保应用程序最相关的部分首先变得交互式来提高感知性能。
选择性注水的关键要素包括:
来源
注水要求客户端渲染的树与服务器上渲染的树完全匹配。当出现不匹配时,React 具有恢复机制:
React 通过以下方式处理不匹配:
来源
React 提供了多种用于服务器渲染和注水的 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 | 包 | 描述 |
|---|---|---|
hydrateRoot() | react-dom/client | 从服务器渲染的 HTML 创建 React 根并注水它 |
典型的服务器端渲染和注水流程如下所示:
renderToPipeableStream 将 React 组件渲染为 HTML 流hydrateRoot 使内容具有交互性来源
Suspense 是 React SSR 策略的关键组成部分,它支持服务器端和客户端的异步渲染。
Suspense 的服务器端实现允许:
来源
服务器端渲染通过更快地向用户展示内容来提高感知性能,但伴随着权衡:
React 的 SSR 实现包含多项优化:
来源
React 为服务器渲染提供了强大的错误处理机制
当服务器渲染期间发生错误时:
在注水过程中,不匹配或错误通过以下方式处理:
来源
React 的服务器端渲染系统为交付快速、交互式 Web 应用程序提供了强大的框架。Fizz 的流式架构,结合 Suspense 集成和渐进式注水,使开发人员能够平衡性能和交互性。
了解这些系统有助于你优化 React 应用程序,从而改善用户体验,特别是对于连接较慢或设备性能较低的用户。