React 18 流式渲染:renderToPipeableStream 的工作原理
了解 renderToPipeableStream 如何在所有异步数据解析完成前,逐步刷新 HTML 分块
React 18 流式渲染:renderToPipeableStream 的工作原理 是 CoddyKit 上的免费 React Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 React Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 React Academy 课程共包含 4 节课。
React 18 之前:同步瓶颈
在 React 18 之前,服务端渲染使用 renderToString,这是同步的:React 会先将整个组件树渲染为字符串,然后再向浏览器发送任何 HTML。如果某个组件需要加载数据,服务器就必须等待所有数据准备完成后,首个字节才能传到用户那里。
React 18:renderToPipeableStream
React 18 引入了 renderToPipeableStream,它会将组件树渲染为 HTML 数据块流。React 不必等待所有内容准备就绪,而是在组件树的各个部分完成后就发送相应的 HTML,使浏览器能够立即开始渲染可见内容。
结构解析:pipe 与 abort
renderToPipeableStream 会返回一个包含两个方法的对象:pipe(writable) 和 abort()。pipe 接受 Node.js Writable 流(通常是 HTTP 响应),并开始向其中传输 HTML。abort() 会取消该数据流,用于请求被取消或超出超时时间的情况。
最先传输的内容:外壳
数据流从 HTML 外壳开始——也就是所有未被待处理的 Suspense 边界阻塞的内容。这包括文档头部、导航、页脚、布局框架以及任何可同步获得的内容。外壳会立即开始传输,早于任何依赖数据的组件完成解析。
数据流中的 Suspense 后备内容
Suspense 边界内等待数据的组件最初会以其后备界面进行传输(例如加载指示器)。React 稍后会发送一个脚本标签,用解析后的内容替换后备界面——整个过程无需在客户端重新渲染外壳。
用于客户端水合的 bootstrapScripts
将 bootstrapScripts: ['/static/js/client.js'] 传递给 renderToPipeableStream,告诉 React 在数据流末尾注入一个脚本标签。浏览器会加载此包并调用 hydrateRoot,将 React 的事件处理器附加到服务端渲染的 DOM 上。
onShellReady:开始传输的正确时机
当 HTML 外壳(待处理的 Suspense 边界之外的所有内容)准备发送时,onShellReady 会触发。这是调用 pipe(res) 的正确时机——但请务必在调用 pipe 之前设置 HTTP 状态码和响应标头,因为开始流式传输后 HTTP 状态就会被锁定。
流式传输前设置标头
由于调用 pipe() 后会立即开始流式传输,因此任何 res.setHeader 或 res.statusCode 赋值都必须在调用 pipe 之前完成。常见做法是在 onShellReady 回调中将状态码设置为 200,并将 Content-Type 设置为 text/html,然后立即调用 pipe(res)。
onShellError:外壳渲染前的致命错误
onShellError 会在外壳完成渲染前发生不可恢复的错误时触发——例如,顶层组件在任何 Suspense 边界之外抛出错误。在这种情况下,您无法流式传输部分响应;相反,应重定向到错误页面,或发送静态错误 HTML 文档。
onAllReady:用于机器人和爬虫
整个 React 树(包括所有 Suspense 边界)都已解析完成时,onAllReady 会触发。对于搜索引擎爬虫和社交媒体链接预览器,您需要发送完整 HTML,而不是进行流式传输。请检查请求是否来自机器人,并在 onAllReady 中调用 pipe(res),而不是在 onShellReady 中调用。
流式传输期间的错误恢复
Suspense 边界中的错误会触发 onError——React 仍可在该边界回退到错误界面的同时继续流式传输页面其余内容。请使用 onError 将错误记录到您的可观测性流水线中,而不要为用户中止流式传输。
onAllReady 与 onShellReady
应该在什么时候使用 onAllReady,而不是 onShellReady 来开始调用 pipe?
课程回顾
renderToPipeableStream 是 Node.js 服务器用于流式 SSR 的基础 API。它通过 onShellReady 立即流式传输 HTML 外壳,在数据解析完成后填充 Suspense 边界,并通过 bootstrapScripts 对客户端进行水合。请对机器人和爬虫使用 onAllReady,在发生致命失败时使用 onShellError,并始终在调用 pipe() 前设置 HTTP 标头。
常见问题解答
「React 18 流式渲染:renderToPipeableStream 的工作原理」课时是免费的吗?
是的 — 「React 18 流式渲染:renderToPipeableStream 的工作原理」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 React Academy 课程的其余内容,请升级到 CoddyKit PRO。 React Academy 课程共包含 4 节课。
「React 18 流式渲染:renderToPipeableStream 的工作原理」这节课中我会学到什么?
了解 renderToPipeableStream 如何在所有异步数据解析完成前,逐步刷新 HTML 分块 你通过在浏览器中直接运行的动手代码来练习 React Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 React Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 React Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。
「React 18 流式渲染:renderToPipeableStream 的工作原理」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 React Academy 课中编写并运行代码吗?
能。每节 React Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- React 18 流式渲染:renderToPipeableStream 的工作原理
- Suspense 边界与流式传输优先级
- 使用选择性水合实现渐进式水合
- 衡量流式传输的影响:FCP、TTI 与 LCP