选择性水合作用 ✔

在之前的文章中,我们介绍了 SSR 和 Hydration 如何改善用户体验。

React 能够(快速)使用 react-dom/server 库提供的 renderToString 方法在服务器上生成一棵树,该方法在整个树生成后发送到客户端。

渲染的 HTML 是非交互式的,直到 JavaScript 包被获取和加载,之后 React 沿着树向下走以获取和附加处理程序。

但是,由于当前实现的一些限制,这种方法可能会导致一些性能问题。

在服务器渲染的 HTML 树能够发送到客户端之前,所有组件都需要准备好。

这意味着可能依赖外部 API 调用或任何可能导致某些延迟的进程的组件最终可能会阻止较小的组件快速呈现。

除了较慢的树生成之外,另一个问题是 React 只对树进行一次水合。
这意味着在 React 能够对任何组件进行水合之前,它需要先获取所有组件的 JavaScript,然后才能对任何组件进行水合。
这意味着较小的组件(带有较小的包)必须等待较大组件的代码被获取和加载,直到 React 能够在您的网站上处理任何内容。在此期间,该网站保持非互动状态。

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

我们现在可以使用服务器上的新 pipeToNodeStream 方法流式渲染 HTML,而不是使用我们之前介绍的 renderToString 方法。

此方法与 createRoot 方法和 Suspense 相结合,可以开始流式传输 HTML,而无需等待较大的组件准备就绪。

这意味着可以在使用 SSR 时延迟加载组件,这在以前(真的)是不可能的!

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

// index.js
import { hydrateRoot } from "react-dom";
import App from './App';

hydrateRoot(document, <App />);

// App.js
import { Suspense, lazy } from "react";
import Loader from "./Loader";

const Comments = lazy(() => import("./Comments"));

function App() {
  return (
    <main>
      <Header />
      <Suspense fallback={<Loader />}>
        <Comments />
      </Suspense>
      <Footer />
    </main>
  )
}

// server.js
import { pipeToNodeStream} from "react-dom/server";

export function render(res) {
  const data = createServerData();
  const { startWriting, abort } = pipeToNodeWritable(
    <DataProvider data={data}>
      <App assets={assets} />
    </DataProvider>,
    res,
    {
      onReadyToStream() {
        res.setHeader('Content-type', 'text/html');
        res.write('<!DOCTYPE html>');
        startWriting();
      }
    }
  );
};

之前减缓了树生成和 TTI 的 Comments 组件现在包含在 Suspense 中。

这告诉 React 不要让这个组件减慢树生成的其余部分。

相反,React 将回退组件作为最初呈现的 HTML 插入,并在发送到客户端之前继续生成树的其余部分。

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

选择性水合使得已经可以对发送到客户端的组件进行水合,甚至在发送 Comments 组件之前!

一旦 Comments 组件的数据准备好,React 开始流式传输该组件的 HTML,以及一个小的 <script> 来替换回退加载器。

React 在注入新的 HTML 后开始水化。

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

流式渲染允许您在组件准备好后立即开始流式传输,而不会因为组件可能需要更长的时间在服务器上生成而导致 FCP 和 TTI 变慢。

组件可以在流式传输到客户端后立即加水,因为我们不再需要等待所有 JavaScript 加载开始加水,并且可以在所有组件都加水之前开始与应用程序交互。



知识点

  • pipeToNodeStream

  • Suspense

此页面上有什么