资讯动态

Gatsby 部分水合(Partial Hydration)实战指南:用 React Server Components 实现按需交互

发布时间:2026/9/19 20:41:51 来源:尧图企业网站定制
Gatsby 部分水合Partial Hydration实战指南用 React Server Components 实现按需交互【免费下载链接】gatsbyReact-based framework with performance, scalability, and security built in.项目地址: https://gitcode.com/gh_mirrors/ga/gatsbyPartial Hydration部分水合是 Gatsby 5 提供的一项实验性性能特性它让你的站点在默认情况下以纯静态 HTML输出只有在真正需要交互的组件上才加载 JavaScript 并在客户端进行水合从而显著降低 Total Blocking TimeTBT与 Time To InteractiveTTI。本文基于官方指南 docs/docs/how-to/performance/partial-hydration.md 展开并结合 packages/gatsby/src/utils/webpack/plugins/partial-hydration.ts 等仓库源码讲解如何开启该特性、如何声明服务器组件与客户端组件、如何优化组件树以及当前存在的限制。读完本文你将掌握在 Gatsby 5 项目中按需引入交互、把 JavaScript 负载降到最低的完整实践方案。前置条件开始之前请确保你的项目满足以下三个条件使用gatsby5.0.0或更高版本。如果还没有项目可以参考 Quick Start 创建。安装reactexperimental与react-domexperimental注意使用--save-exact锁定版本并用--legacy-peer-deps绕过 peer 依赖校验npm install --save-exact reactexperimental react-domexperimental --legacy-peer-deps在gatsby-config.js中开启PARTIAL_HYDRATION实验性 flagmodule.exports { flags: { PARTIAL_HYDRATION: true } }从源码角度看该 flag 定义于 packages/gatsby/src/utils/flags.ts它被标记为experimental: true仅作用于build命令并绑定环境变量GATSBY_PARTIAL_HYDRATION。同时 packages/gatsby/src/utils/webpack.config.js 也会读取该环境变量true或1作为 webpack 配置的开关。此外flag 的校验逻辑要求 Gatsby 主版本为 5且 React 版本满足18.0.0或实验性的^0.0.0否则会提示 “Partial hydration requires React 18 to work.”。这解释了为什么必须搭配 React 的实验性版本使用。服务器组件默认即静态开启 Partial Hydration 之后所有组件默认都是服务器组件server components。在gatsby build生成的 HTML 中服务器组件不会携带任何客户端 JavaScript这带来了开箱即用的性能提升。Gatsby 从顶层页面开始生成服务器组件——即src/pages目录下的页面或通过createPageAPI 创建的页面。整棵组件树包括 layout、模板、内容组件默认都以服务端渲染的方式输出为静态 HTML。React Server Components 是 React 社区的一项提案其核心思想是在服务端完成组件的渲染工作只把渲染结果而非组件代码发给客户端。Gatsby 正是借助它来实现 Partial Hydration关于底层原理可进一步阅读仓库中的概念指南 docs/docs/conceptual/partial-hydration.md。客户端组件用 use client 声明边界如果你的组件需要交互性事件处理、状态、生命周期就必须把它标记为客户端组件。客户端组件的 HTML 会在客户端进行 hydration——即用客户端 JavaScript 为服务端渲染出的 HTML 补充应用状态与交互能力。标记方式是在组件文件的第一行代码加上use client指令use client import * as React from react const Joke () { const [isShown, show] React.useReducer(() true, false) return ( main button onClick{show}Show me a joke/button {isShown pWhy couldnt the React component understand the joke? Because it didnt get the context./p} /main ) } export default Joke源码如何识别 use client在构建层面webpack 插件PartialHydrationPlugin位于 packages/gatsby/src/utils/webpack/plugins/partial-hydration.ts通过解析器钩子扫描每个模块的 AST当发现ExpressionStatement且其指令值为use client时就会把module.buildInfo.rsc标记为true见 partial-hydration.ts。这个标记会保留在热更新/增量构建的缓存中因此不必每次构建都重新解析模块。随后所有被标记的客户端模块会被收集并从async-requires中移除页面模板的静态 import避免模板代码被无条件打入客户端 bundle同时生成一份客户端组件清单manifest记录每个客户端组件的模块 ID、导出名与所在 chunk见 partial-hydration.ts。这份 manifest 会与上次构建的结果合并后写入构建产物供运行时的服务端渲染引用。何时需要使用客户端组件官方建议能用服务器组件就用服务器组件只对确实需要交互的部分选择性声明客户端组件。以下场景必须使用客户端组件交互与事件监听如onClick()、onChange()等状态与生命周期方法如useState()、useEffect()等仅浏览器可用的 API如访问window上的属性React Class 组件。FAQ常见问题与最佳实践是否每个交互组件都要加 use client不需要。你只需在被服务器组件直接 import 的组件上添加use client指令从而在服务器组件与客户端组件之间建立起一条清晰的“客户端边界client boundary”。客户端组件内部再 import 的其他客户端组件无需重复添加指令。举例说明假设src/pages/index.jsx导入了SocialMedia而SocialMedia内部又导入了Instagram和Twitter。由于默认所有组件都是服务器组件而这三个组件都使用了useEffect()因此你需要把组件标记为客户端组件——但只需在SocialMedia上添加use client指令因为它是唯一一个被服务器组件页面直接导入的客户端组件。如何优化组件树组织组件结构时应尽可能把客户端组件下沉到组件树的叶子节点从而最小化发送到客户端的 JavaScript 体积。例如假设共享的 layout 组件包含一个用于展示最新推文的交互式 footer。与其把整个 layout 标记为客户端组件不如把 footer 拆成独立组件只标记 footer 为交互式use client import * as React from react const Footer () { React.useEffect(() { // do fetching stuff }) return ( footerMy Tweets/footer ) } export default Footerimport * as React from react // Footer is a client component import Footer from ./footer const Layout ({ children }) ( main{children}/main Footer / / ) export default Layout这样layout 本身仍是服务器组件只有 footer 的 JavaScript 会被下发到客户端。能否在客户端组件中导入服务器组件不能直接导入。但你可以把服务器组件作为childrenprop 传给客户端组件React 会同时实例化客户端与服务器组件。先在客户端组件中声明一个childrenpropuse client import * as React from react export const MyClientComponent ({ children }) ( div pRe-Hydrated on the client/p {children} /div )然后在页面中使用MyClientComponent并把服务器组件作为children传入import * as React from react import { MyServerComponent } from ../components/my-server-component import { MyClientComponent } from ../components/my-client-component const Page () ( MyClientComponent MyServerComponent / /MyClientComponent ) export default Page如何从服务器组件向客户端组件传 props大部分情况下与普通应用无异但从服务器传到客户端的 props 必须是可序列化serializable的——例如函数或回调无法传递// OK const Page () ClientComponent colorrebeccapurple / // ⚠️ Doesnt work const Page () ( ClientComponent onClick{() console.log(Hello World)} / )当前限制使用 Partial Hydration 时请注意以下限制必须使用 React 的实验性发布版本reactexperimental官方不建议在生产环境使用React 生态中很多包尚未兼容 React Server Components例如 CSS-in-JS 类方案Partial Hydration仅在gatsby build与gatsby serve时生效在gatsby develop中不生效。从构建流程看这一限制也体现在源码中packages/gatsby/src/commands/build.ts 会在PARTIAL_HYDRATION开启时通过buildPartialHydrationRenderer额外编译一套服务端渲染器 bundle 并生成对应的 webpack 编译产物而开发模式并不走这条路径同时 flags.ts 将该 flag 的command限定为build进一步印证了它只面向生产构建阶段。总结Partial Hydration 是 Gatsby 5 中降低前端 JavaScript 体积、改善核心性能指标TBT / TTI的重要实验性特性。核心实践可以归纳为四点在gatsby-config.js开启PARTIAL_HYDRATIONflag并安装reactexperimental默认把所有组件当作服务器组件静态内容零客户端 JavaScript仅在需要交互的地方添加use client指令并尽量把客户端组件下沉到组件树叶子牢记限制实验性 React、生态兼容性、以及仅在build/serve下生效。若想深入理解 Gatsby 如何基于 React Server Components 实现这一机制建议继续阅读概念指南 docs/docs/conceptual/partial-hydration.md并结合 PartialHydrationPlugin 源码 追踪 use client 指令从解析到生成客户端组件 manifest 的完整链路。【免费下载链接】gatsbyReact-based framework with performance, scalability, and security built in.项目地址: https://gitcode.com/gh_mirrors/ga/gatsby创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价