React 18: Selective Hydration

经过上两篇文章的铺垫,我们终于可以介绍 React 18 最激动人心的特性了!(个人排行

移动端 Web 前端性能优化 这篇文章中,提到了一种分块渲染的优化手段。实际上这种方法在业界使用并不广泛(我们组在业务上已经投入使用,效果显著),主要是因为没有成熟的开箱即用方案,流程较为复杂。而 React 18 似乎即将解决掉这个老大难问题,用一种十分优雅的手段提供了开箱即用的分块渲染。

如果你还不知道什么是分块渲染,请先看看上面这篇文章的相关段落~

本文的主要介绍内容,都是来自这篇文章。可以直接看原文,比我讲的肯定好。

首先,React 18 中,Suspense 将可以在 SSR 时使用。在 React 16 中,如果在服务端渲染时使用 Suspense 将会直接报错。在 React 18 中,如果使用非流式渲染,即 renderToString ,那么 Suspense 部分将会变为 CSR 。如果使用新的流式渲染 API,即 renderToPipeableStream ,那么 Suspense 部分将不会阻塞 SSR,而是自动变为分块渲染模式。

在这一模式下,被 Suspense 的组件将会先渲染它的 fallback。

当 Suspense 组件准备好之后,服务端将会继续流式输出这一组件,并插入一段 inline 的脚本,将 fallback 内容替换为准备好的内容。这一阶段不依赖 React 的客户端部分,即使 React 的 JS 还没有加载完成也可以进行。

到此为止,就是我们一般分块渲染会实现的部分了。但 React 18 还提供了分块 Hydration 的功能。也就是说,无需等待所有 Suspense 的组件加载完成,就可以对其他组件进行 Hydration。也就是说,在 React 18 中,Suspense 不仅会把组件标记为不阻塞流式渲染,还不会阻塞 Hydration!

比如说上图这个例子,右下角组件使用了 React.lazy 进行 Code Spilting,所以这个组件的 JS 可能会更迟加载,但是这一组件 JS 尚未加载完成的时候,其他组件已经可以进行 Hydration 了!而这一切都是 React 进行管理和调度的,只需要用 Suspense 包裹右下角组件即可。

当右下角组件的 JS 加载完毕后,React 会再对这一组件进行单独的 Hydration。

更进一步,如果 HTML 还没有流式输出完,而 React 已经加载成功,那么 React 也不会等还在 Suspense 的组件,而是先回去 Hydrate 已经输出完的组件,做到时间利用最大化。这是目前的分块渲染方案还做不到的。

右下角组件还没流式输出完,但其他组件已经 Hydration 完毕

得益于 React 18 的分片和优先级机制,React 还可以终端 Hydration,去优先处理用户交互。

例如上图,当右下角组件正在 Hydration 的时候,用户点击了左侧组件,此时 React 会在下一个时间分片优先处理点击事件导致的视图更新,之后才继续右下角组件的 Hydration。

而假如右下角组件正在等待 Hydration,左侧组件正在 Hydration,此时用户点击了右下角组件。则 React 会以最高优先级、同步地进行右下角组件的 Hydration,然后响应用户交互,更新视图后,再继续对左侧组件进行 Hydration。

而这一切都是 React 自身进行调度和处理的,只需要你使用 Suspense 去管理组件的加载态,剩下的一切 React 都会帮你完成。

通过这三篇文章,React 18 的主要新功能和带来的特性基本已经介绍完毕。可以看出来,尽管 React 18 在 API 上的改动很小,迁移难度很低,但带来的好处是巨大的。React 似乎变成了 ReactOS,引入了时间分片和优先级调度,让许多之前无法实现的功能成为可能。React 18 后续的 Roadmap 也非常诱人,相信 React 的生态会越来越繁荣。

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注