mcpField
R
react-selective-hydration

react-selective-hydration

github.com/patternsdev开发257960 次安装28 周前更新
代码仓库

关于 react-selective-hydration

面向 React 18 SSR 开发者的选择性水合指南,说明如何通过流式渲染和 Suspense,让已就绪的页面部分先变为可交互,而不必等待所有组件。

主要功能

  1. 01使用 Suspense 划分水合区域
  2. 02通过流式 SSR 提前发送 HTML
  3. 03慢速组件不阻塞同级内容
  4. 04组件到达客户端后即可水合

适用场景

  1. 01让 SSR 页面部分内容先可交互
  2. 02避免数据获取组件阻塞页面水合
  3. 03在大型组件加载期间保持关键区域可用

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/patternsdev/skills --skill react-selective-hydration

安装后在 Claude Code 中输入/react-selective-hydration确认已加载。

详细介绍

选择性水合

在之前的文章中,我们介绍了带水合的 SSR 如何改善用户体验。React 可以使用 react-dom/server 库提供的 renderToString 方法,在服务器上快速生成一棵树,并在整棵树生成后将其发送到客户端。渲染后的 HTML 无法交互,直到 JavaScript 包被获取并加载完毕,之后 React 才会遍历这棵树进行水合并附加事件处理器。

然而,由于当前实现存在一些限制,这种方式可能会导致一些性能问题。

适用场景

  • 如果你希望 SSR 页面中的部分内容在所有 JavaScript 加载完成前即可交互,请使用此方式
  • 如果加载缓慢的组件(例如,获取数据的组件)阻塞了整个页面的水合,此方式会很有帮助

说明

  • 使用 Suspense 边界划分可独立水合的 UI 区块
  • 使用 renderToPipeableStream(Node)或 renderToReadableStream(edge)实现流式 SSR
  • 将耗时较长的数据获取组件放在 Suspense 内部,避免其延迟同级组件的水合
  • 确保关键的交互组件不处于持续时间较长的加载回退 UI 中
  • 使用 hydrateRoot(React 18+)以利用选择性水合

详情

在服务端渲染的 HTML 树能够发送到客户端之前,所有组件都必须准备就绪。这意味着,依赖外部 API 调用或任何可能造成延迟的流程的组件,可能会阻碍较小的组件快速完成渲染。

除了树生成速度较慢之外,另一个问题是 React 只会对树进行一次水合。这意味着,在 React 能够对任何组件进行水合之前,它需要先获取所有组件的 JavaScript。这意味着,较小的组件(代码包更小)必须等待较大组件的代码获取并加载完毕,React 才能对网站上的任何内容进行水合。在此期间,网站一直无法交互。

React 18 通过允许我们将流式服务端渲染与一种新的水合方式相结合,解决了这些问题:选择性水合!

现代 React SSR 不再使用 renderToString,而是在 Node 运行时中使用 renderToPipeableStream(),或在 Web Stream 运行时中使用 renderToReadableStream()。

这些 API 与 hydrateRoot() 和 Suspense 结合后,即可在无需等待较大组件准备就绪的情况下开始流式传输 HTML。这意味着,在使用 SSR 时,我们可以延迟加载组件,而不会阻碍页面其余部分的水合。

之前拖慢树生成速度和 TTI 的 Comments 组件,现在被包裹在 Suspense 中。这会告诉 React,不要让此组件拖慢其余树的生成速度。相反,React 会将回退组件作为初始渲染的 HTML 插入,并继续生成其余的树,然后再将其发送到客户端。

与此同时,我们仍在获取 Comments 组件所需的外部数据。

选择性水合使我们能够在 Comments 组件发送到客户端之前,就对已经发送到客户端的组件进行水合!

Comments 组件的数据准备就绪后,React 会开始流式传输此组件的 HTML,以及一个用于替换回退加载器的小型 <script>。

注入新的 HTML 后,React 会开始水合。

React 18 修复了人们使用 React SSR 时经常遇到的一些问题。

流式渲染允许你在组件准备就绪后立即开始流式传输,而不会因为某些组件在服务端生成耗时较长而导致 FCP 和 TTI 变慢。

组件一旦流式传输到客户端,就可以立即进行水合,因为我们不再需要等待所有 JavaScript 加载完毕才能开始水合;即使尚未对所有组件完成水合,也可以开始与应用交互。

来源

参考资料

评论

支持 Markdown