0Pricing
React Academy · 课时

选择性水合与 HTML 流式传输

使用 Suspense 边界传输 HTML 片段,并优先水合可交互的岛屿。

选择性水合与 HTML 流式传输 是 CoddyKit 上的免费 React Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 React Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 React Academy 课程共包含 4 节课。

整页水合的问题

传统 SSR 会一次性对整页进行水合。如果页面的一部分包含大量 JavaScript(例如地图或图表),就会阻塞其余部分的水合,包括简单的交互式按钮。

使用 renderToPipeableStream 流式传输 HTML

React 18 的流式接口会分块发送 HTML。页面外壳会立即到达;Suspense 边界会在内容解析后逐步填充,用户无需等待所有数据就绪即可看到用户界面。

const { pipe } = renderToPipeableStream(<App />, {
  bootstrapScripts: ['/bundle.js'],
  onShellReady() {
    res.setHeader('content-type', 'text/html');
    pipe(res);
  },
  onError(error) {
    console.error(error);
  },
});

流式渲染在实践中的工作方式

React 会立即渲染不会暂停的组件(外壳)。当 Suspense 边界的数据解析后,React 会发送一个 HTML 块来填充该边界,并附带一个脚本标签,指示浏览器将其放置到相应位置。

选择性水合

使用流式渲染时,React 18 可以独立地对组件进行水合。如果用户点击了尚未完成水合的元素,React 会优先对该组件进行水合,然后继续处理其余部分。

将 Suspense 边界作为流式传输单元

每个 <Suspense> 边界都是一个流式传输单元。回退内容会立即发送,实际内容稍后再以流的形式传输。嵌套 Suspense 边界,以便按合适的粒度进行流式传输。

function App() {
  return (
    <Layout>
      {/* Streams first — no data needed */}
      <Header />
      <Suspense fallback={<ArticleSkeleton />}>
        {/* Streams when article data resolves */}
        <Article />
      </Suspense>
      <Suspense fallback={<CommentsSkeleton />}>
        {/* Streams independently from Article */}
        <Comments />
      </Suspense>
    </Layout>
  );
}

Next.js 中使用 loading.tsx 进行流式传输

在 Next.js 应用路由器中,loading.tsx 就是 Suspense 回退内容。页面外壳(布局)会先进行流式传输;页面内容会在其异步函数解析后进行流式传输。

// app/blog/loading.tsx — shown while page.tsx data loads
export default function Loading() {
  return <ArticleSkeleton />;
}

// app/blog/page.tsx — fetches data, streams when ready
export default async function BlogPage() {
  const posts = await fetchPosts(); // data fetch happens server-side
  return <PostList posts={posts} />;
}

Suspense 中的客户端组件

服务端组件使用 Suspense 进行数据流式传输。客户端组件使用 Suspense 进行延迟加载。两者都能从选择性水合中受益。

// Lazy-loaded client component — hydrates selectively
const HeavyChart = lazy(() => import('./HeavyChart'));

function Dashboard() {
  return (
    <Suspense fallback={<ChartSkeleton />}>
      <HeavyChart />
    </Suspense>
  );
}

基于优先级的水合

如果用户与尚未完成水合的组件进行交互(例如点击它),React 18 会先同步水合该组件,然后再完成页面其他部分的水合。

onShellReady 与 onAllReady

当外壳(未被挂起的部分)准备好进行流式传输时,会触发 onShellReady。当所有内容都渲染完成时,会触发 onAllReady——这适用于静态生成,或您必须一次性发送完整 HTML 的场景。

// For streaming (progressive rendering):
onShellReady() { pipe(res); }

// For full HTML (e.g., static export, SEO bots):
onAllReady() { pipe(res); }

Abort 控制器

将 AbortController 信号传入,以取消执行缓慢的 SSR(例如超过超时限制时)。

const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 5000); // 5s timeout

const { pipe } = renderToPipeableStream(<App />, {
  signal: controller.signal,
  onShellReady() { pipe(res); },
});

clearTimeout(timeoutId);

衡量流式传输的影响

使用 Lighthouse 或 WebPageTest,在启用流式传输前后测量首字节时间(TTFB)和最大内容绘制(LCP),以量化改进效果。

快速检查

在 React 18 的选择性水合中,如果用户点击了一个尚未完成水合的元素,会发生什么?

回顾

流式 SSR 使用 renderToPipeableStream 和 Suspense 边界逐步发送 HTML。每个 Suspense 边界都可以独立进行流式传输。选择性水合会优先处理用户交互过的元素。在 Next.js 中,loading.tsx 是页面级流式传输的自动 Suspense 回退内容。

常见问题解答

「选择性水合与 HTML 流式传输」课时是免费的吗?

是的 — 「选择性水合与 HTML 流式传输」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 React Academy 课程的其余内容,请升级到 CoddyKit PRO。 React Academy 课程共包含 4 节课。

「选择性水合与 HTML 流式传输」这节课中我会学到什么?

使用 Suspense 边界传输 HTML 片段,并优先水合可交互的岛屿。 你通过在浏览器中直接运行的动手代码来练习 React Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 React Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 React Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。

「选择性水合与 HTML 流式传输」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 React Academy 课中编写并运行代码吗?

能。每节 React Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. React SSR 的底层工作原理
  2. 水合错误:原因与修复
  3. 选择性水合与 HTML 流式传输
  4. 岛屿架构模式
← 返回 React Academy