在本文中,我们将讨论预渲染和 Hydration,以及为什么在构建单页面应用程序时它们是很重要的特性。 通过正确的 Hydration ! 什么是 Hydration? Hydration 是为我们的应用程序添加交互性的。它加载使我们的应用程序具有交互性的 JavaScript。 相反,它会选择哪些元素需要更新 预渲染和 Hydration 的实际应用 在预渲染和 Hydration 流程中,首先,用户会看到具有正确内容的 HTML。 然后 Hydration 开始发挥作用,加载 JavaScript 以使应用程序具有交互性。 我们所有的 React 组件将始终在客户端进行 Hydration,即使它们没有必要这样做。
为HagiCode设计12种极致的启动体验:从极简到赛博朋克在React19应用下载和Hydration的短暂间隙,是留给用户感知品牌个性的黄金窗口。 然而,这种架构带来了一个经典的用户体验痛点:当用户访问网页时,浏览器需要先加载HTML,再下载巨大的JSBundle,最后由React执行Hydration(注水)。 本文作者:newbe36524本文链接:https://hagicode-org.github.io/site/blog/2026-02-03-hagicode-react-19-hydration-splash-screen
toc 让建站酷起来 SSR SSG ISR 轮询式刷新 按需刷新 Edge Rendering 酷的“代价” Hydration Selective Hydration Islands Architecture No hydration 没噱头的remix Intro React, Vue, Angular 三足鼎立之后,前端界又开始“卷起来了”,不过战火已经单页渲染蔓延到了服务端渲染建站 NextJs成名已久,功能全面,astro Island 独步天下,qwik No hydration 异军突起。remix 守正出奇,无招胜有招。 今天我们来一块说道说道。 这里实际上就涉及Hydration注水的概念。 Hydration Hydration注水,大家可能较少听到,但是它却是现代前端spa,mpa同构框架的关键。 Selective Hydration 渐进可选式的注水,这里的代表就是大名鼎鼎的React,借助于fiber架构,React能够打断传统递归式的注水,让应用能够优先处理交互事件,这里框架层面比较复杂,
这个错误通常发生在 React 的 服务端渲染(SSR)或静态生成(SSG) 场景中,当组件在 hydration(水合)过程中(即客户端接管渲染时)收到了新的更新(如状态或 props 变化) 状态初始化延迟: 组件在 hydration 后(如 useEffect 中)才初始化状态(如 setState),导致客户端渲染的初始状态与服务端不一致。 路由切换或动态路由: 在动态路由场景中,服务端渲染的页面可能与客户端导航后的路由参数不匹配,导致客户端 hydration 后触发新的数据加载和状态更新。 它允许 React 在 hydration 过程中优先完成服务端渲染的水合流程,再将客户端的更新作为“过渡”处理,避免强制切换渲染模式。 前触发更新 确保组件在 hydration 完成前(即 useEffect 执行前)不触发状态更新。
NextJs成名已久,功能全面,astro Island 独步天下,qwik No hydration 异军突起。remix 守正出奇,无招胜有招。今天我们来一块说道说道。 这里实际上就涉及Hydration注水的概念。HydrationHydration注水,大家可能较少听到,但是它却是现代前端spa,mpa同构框架的关键。 Selective Hydration渐进可选式的注水,这里的代表就是大名鼎鼎的React,借助于fiber架构,React能够打断传统递归式的注水,让应用能够优先处理交互事件,这里框架层面比较复杂,具体效果怎么样也有待观察 --><MyReactComponent client:load />No hydration最快的注水,就是无注水。这就是qwik 框架的主要卖点。
今天聊一聊上手 next.js 使用中常会出现的一类报错:hydration fail,估计大部分使用过 next.js 开发的同学对下面的报错信息一定都很熟悉: Error: Hydration failed 报错的原因报错信息中已经说的很清楚:由于 hydration 后的 UI 和服务端渲染的 UI 不一致导致 hydration 失败。 不过虽然报错信息写着 Hydration failed,但实际上还是会以 Hydration 后的 UI 为准的,其实勉强算是 hydration 成功的。 实际场景 下面讲一个实际的场景。 但是在 SSR + hydration 的场景下,React 的 hydration 会检查 UI 的一致性,前后数据不一致就会导致 hydration 错误的发生。 如果对 hydration fail 错误的解决有其它方案的同学欢迎留言。
这个称为选择性 hydration 的功能,允许在其余 HTML 和 JavaScript 代码完全下载之前,就对可用的部分进行 hydration。 主内容区的代码加载完成后,就会进行 hydration。 得益于选择性 hydration,即使是体积庞大的 JS 代码也不会阻止页面其他部分变得可交互。 以下是利用 <Suspense> 实现选择性 hydration 的直观展示: 此外,选择性 hydration 解决了第三个问题:“要与任何东西互动,必须对所有东西进行 hydration”。 在多个组件等待 hydration 的情况下,React 会根据用户的交互行为来优先处理 hydration。 侧导航的 hydration 则会稍后进行。
,无法完成 partial hydration。 Hydration,主要有如下的几个特点: 在完整的 HTML 渲染之前就可以进行组件的 hydrate,而不用等待 HTML 的内容发送完毕 hydration 可中断。 Partial Hydration。 Hydration 没有这个限制。 因此,虽然两者都是在 Hydration 上做文章,但其实是两种完全不同的方案,而且 Partial Hydration 更加通用,限制更少,执行的 JS 更少。
React 18 官方支持了渐进式水合(官方叫 Selective Hydration)。 要深入了解 Progress Hydration, 可以看这个视频。 Selective Hydration - 选择性水合 选择性水合(Progressive Hydration) 是 渐进式水合(Progressive Hydration) 和 流式SSR(SSR 比较典型的慢组件是异步数据获取的组件, 如下图,未开启 Selective Hydration 的情况,会等待所有异步任务完成后才开始输出,而 Selective Hydration 可以跳过这些组件, 在客户端 Selective Hydration 的运行过程同 Progressive Hydration 。 关于 Selective Hydration 细节,可以阅读以下文章: New in 18: Selective Hydration New Suspense SSR Architecture in React
其次,这一变化允许让我们可以移除 hydrate 方法并替换为 root 上的一个选项;删除渲染回调,这些回调在部分 hydration 中是没有意义的。 什么是 hydration ? 我们已经把 hydrate 函数移到了 hydrateRoot API 上。 from 'App'; const container = document.getElementById('app'); // Create *and* render a root with hydration 如果你想在 hydration 后再次更新 root,你可以将它保存到一个变量中,就像使用 createRoot 一样,然后调用 root.render(): import * as ReactDOM 对于部分 hydration 和渐进式 SSR,这个回调的时间将不符合用户的期望。
客户端 Hydration 性能瓶颈:React 18 的渐进式 Hydration 仍存在冗余计算问题。 智能 Hydration 优化: 引入选择性 Hydration,仅对交互组件进行 Hydrate,减少主线程阻塞。 支持并行 Hydration,利用 Web Workers 加速交互就绪时间。 高薪岗位技能矩阵职级核心能力要求薪资范围(国内)初级掌握基础 SSR 配置15-25K中级优化 Hydration 性能25-40K高级设计企业级 SSR 架构40-70K专家主导框架级性能优化70K+ 学习路径推荐基础入门:Next.js 14 + React 19 官方文档 进阶实战:手写简易 SSR 框架(理解 Hydration 流程) 企业级优化:性能监控(Lighthouse + Web
SSR for Suspense 完整名称是:Streaming SSR with selective hydration。 即便 SSR 内容打到了页面上,由于 JS 没有加载完毕,所以根本无法进行 hydration,整个页面处于无法交互状态。 即便 JS 加载完了,由于 React 18 之前只能进行整体 hydration,可能导致卡顿,导致首次交互响应不及时。 hydration 的过程也是逐步的,这样不会导致一下执行所有完整的 js 导致页面卡顿(hydration 其实就是 React 里写的回调注册、各类 Hooks,整个应用的量非常庞大)。 hydration 因为被拆成多部,React 还会提前监听鼠标点击,并提前对点击区域优先级进行 hydration,甚至能抢占已经在其他区域正在进行中的 hydration。
当 hydration 过程完成后,会由我们的客户端框架接管网站的后续渲染。 hydration 上述过程中有一个非常重要的关键字 hydration(水合)。 首次访问页面时,页面的静态 HTML 是在服务端生成的。 当 JS 脚本下载完成后,会立即执行同时发生一种被称为 hydration 的过程。 针对于上面的概念,我们直接来看看 qwik 中提到的 Hydration is Pure Overhead (完全多余的 Hydration)。 这样做的好处是在 qwki 中完全可以省略 hydration 的多余步骤,甚至可以说完全抛弃了 hydration 的概念。
当 hydration 过程完成后,会由我们的客户端框架接管网站的后续渲染。 1)hydration 上述过程中有一个非常重要的关键字 hydration(水合)。 首次访问页面时,页面的静态 HTML 是在服务端生成的。 针对于上面的概念,我们直接来看看 qwik 中提到的 Hydration is Pure Overhead (完全多余的 Hydration)。 1)Hydration 造成的开销 首先针对于 Hydration 的过程,我们提过到首先会在服务器上进行一次静态 HTML 渲染,之后当 HTML 下发到客户端后又会再次进行 hydrate 的过程, 这样做的好处是在 qwki 中完全可以省略 hydration 的多余步骤,甚至可以说完全抛弃了 hydration 的概念。
大型 SPA(如管理平台、社交平台): 更适合 CSR 或 SSR + Hydration 的形式。SSR 提供初始页面的内容渲染,Hydration 让前端具备 SPA 的流畅体验。5. 5.3 渐进增强与客户端 Hydration渐进增强:优先给用户展示基本可用的内容(SSR 方案),然后在浏览器加载完脚本后进行Hydration——注入交互事件、动画、异步请求等高级功能。 客户端 Hydration:在初次渲染后的静态 DOM 上“激活”或“绑定” JavaScript 事件,使页面具备与纯 CSR 相同的交互体验。 应用示例:对于需要兼顾 SEO 与高交互的页面,可先在服务端输出初始 HTML,客户端再 Hydration,实现性能和交互的双赢。6. 渐进式框架:例如 Astro、Qwik 等新一代框架主打“零 JS 负载”或延迟 Hydration 的概念,进一步优化首屏渲染。
带有 (Re)Hydration 的服务端渲染(SSR + CSR) 带有 (Re)Hydration 的服务端渲染时,从服务器返回的 HTML 页面还包含一个脚本,该脚本可加载完整的客户端应用程序。 对于 Vue,Markus Oberlehner 发布了一份指南,该指南指明在用户交互时使用 hydration[26] 或 vue-lazy-hydration[27](一种早期插件,可在组件可见时或特定用户交互时激活组件 你也可以使用 Preact 和 Next.js 实现部分 hydration[29]。 对于React,部分 “hydration” 功能在 Suspense 计划之中[30](看起来很有希望实现[31]!)。 ivy-universal [29] 使用 Preact 和 Next.js 实现部分 hydration: https://medium.com/@luke_schmuke/how-we-achieved-the-best-web-performance-with-partial-hydration
细数 SSR 的利与弊》列举了 SSR 渲染模式的 6 大难题: 难题 1:如何利用存量 CSR 代码实现同构 难题 2:服务的稳定性和性能要求 难题 3:配套设施的建设 难题 4:钱的问题 难题 5:hydration 典型的,交互逻辑与组件渲染机制绑定在了一起,这是 SSR 需要 hydration 的根本原因: 客户端接到 SSR 响应之后,为了支持(基于 JavaScript 的)交互功能,仍然需要创建出组件树, 与 SSR 渲染的 HTML 关联起来,并绑定相关的 DOM 事件,让页面变得可交互,这个过程称为 hydration 也就是说,只要仍然依赖组件这层抽象,hydration 的性能损耗就无可避免。 然而,在 low-code 模式下,其输出产物(配置数据)也是一种抽象描述形式,如果能够具有与组件同等的表达力,就完全有可能去掉组件这层抽象,不必再背负 hydration 的性能损耗 另一方面,对于无交互 (纯静态展示)、弱交互(静态展示带埋点/跳转)的偏静态场景,low-code 平台也能准确地识别出来,避免不必要的 hydration 难题 6:数据请求 服务端同步渲染要求先发请求,拿到数据后才开始渲染组件
缓慢的Hydration、卡顿的UI、愤怒的用户、流失的转化率。 技术深度解析:为什么服务端组件是数据密集型场景的王者? 1. TTFB优化的本质差异 让我们从底层原理说起。 客户端渲染流程: DNS解析 → TCP连接 → HTML下载 → JS Bundle下载 → 解析执行 → 数据请求 → 渲染 → Hydration 服务端组件流程: DNS解析 → TCP连接 from'moment'; import lodash from'lodash'; // Bundle size: ~800KB (gzipped: ~250KB) // + 数据请求的额外往返时间 // + Hydration /> <MetricsTable data={data.metrics} />
二、服务器端渲染和hydration增强 根据Angular的年度开发者调查,服务器端渲染是Angular的第一大改进方向。 在过去的几个月里,Angular与ChromeAurora团队合作,改善了hydration和服务器端渲染的性能和DX。今天,Angular带来了完整应用非破坏性hydration的开发者预览。 对于执行手动 DOM 操作的组件,在模板中使用 ngSkipHydration 属性逐步采用 hydration。 在早期测试中,我们看到 Largest Contentful Paint 通过全应用程序 Hydration 作用提高了45%。 2.2 Hydration 和服务端渲染的下一步 v16 中的工作只是一块垫脚石,我们计划在这里做更多的工作。
Nuxt.js 3.16引入懒加载hydration提升性能。Google发布轻量级开源模型Gemma 3及安全检查器ShieldGemma2。 Nuxt.js 添加惰性水合 Nuxt.js 3.16 版本增加了对原生延迟/懒加载 hydration 的支持,这使开发人员可以精确控制组件何时进行 hydration。 懒加载 hydration 可以提高初始加载性能和可交互时间,Nuxt 核心团队负责人 Daniel Roe 写道。 懒加载 hydration 旨在控制这些交互式部分何时变为活动状态。两者经常结合使用,因为懒加载 hydration 可以优化各个“岛屿”的 hydration。 此次更新还包括其他功能和性能增强。