【翻译】React 19.2:进一步推进INP 优化

31 阅读6分钟

原文链接:calendar.perfplanet.com/2025/react-…

作者:Michal Matuška

去年在《有效优化React中INP的5个技巧》一文中,我们重点探讨了开发者在优化React时常被低估的关键点。

React并非天生快速,常见的JavaScript构造也可能引发耗时任务。更大的DOM和更多组件意味着渲染过程中的工作量增加,交互时的UI响应变慢。实际中这往往导致即使相对简单的用户操作也需数百毫秒完成,致使INP指标飙升。

React 19.2版本的发布带来了新特性,为开发者提供了理解React内部运作的新工具。现在可以更好地控制应用程序何时以及如何占用浏览器的主线程。

让我们深入探讨其中两个关键的新特性。

全新组件 <Activity />

这项新功能解决了开发者长期面临的难题:如何在有效隐藏用户界面部分区域的同时保留其状态,避免每次隐藏组件时都强制浏览器进行完整的React渲染。

// Either we have lost the state of the component due to a condition
{isVisible && <Sidebar />}
// Or we unnecessarily rendered an invisible component
<div style={{display: isVisible ? '' : 'none'}}>
  <Sidebar />
</div>

<Activity>组件正是为解决此类场景而生。通过mode参数,它可切换组件的可见状态,并按预期管理渲染周期。该参数当前支持两种设置:hidden(隐藏)和 visible(可见),React会根据设置动态调整处理逻辑。

状态保存与低优先级渲染

当组件切换至 mode="hidden" 时,React 不会将其从 DOM 中卸载。而是通过视觉隐藏实现,即为包裹元素应用 display:none 样式。这带来两大显著优势:

  • 本地状态保留:所有组件状态(useStateuseReducer)及上下文均保留在内存中,当组件重新可见时可立即恢复。
  • DOM状态的保留:<input>字段中的文本、滚动位置或选中标签页等元素的状态得以保存,因为其DOM节点并未被销毁。

另一优势在于:尽管组件仍处于挂载状态,React在概念上将其视为已卸载,并移除所有 useEffect 钩子。这确保了隐藏的UI区域不会接收数据、启动计时器等操作,从而大幅降低系统和内存负载。

// Sidebar is hidden, preserves state, low-priority update
<Activity mode="hidden">
  <Sidebar />
</Activity>
// Sidebar is visible, updates like a regular component
<Activity mode="visible">
  <Sidebar />
</Activity>

活动内部的组件在父级数据(props)发生变化时仍可能重新渲染。但React会将此类更新置于最低优先级处理。隐藏内容的更新仅在页面可见区域无关键任务(如用户交互)时才会执行。

预渲染

包裹在<Activity>中的内容会在加载过程中为用户预先准备,避免用户界面冻结。

这显著加快了导航、标签切换及其他界面显示的速度,因为React无需在用户首次激活时才渲染全部内容。

选择性注入支持

<Suspense>类似,<Activity>将组件树划分为独立单元,使React能够有选择地为应用程序的局部区域注入数据。因此前述的预渲染操作优先级较低。React通过这种方式将工作分解为独立片段。这一概念对性能而言堪称奇迹。

组件树按优先级划分。红色组件标记为次要组件。

值得注意的是,<Activity> 也可省略 mode 参数,仅用于启用选择性加载。

关于SSR的说明

在服务器端渲染(SSR)过程中,React 完全不会将隐藏的 Activity 组件插入 HTML 中。请务必谨慎对待此特性,因为它可能对 SEO 产生负面影响。例如,通过这种方式隐藏 mega-menu 可能会影响子页面的索引,这显然是您不希望看到的。相反,该特性适用于各类登录模态框、筛选功能等场景。

React 团队未来很可能会为 mode 属性增加更多选项,从而满足我们的 SEO 需求。

Chrome 开发者工具中的性能跟踪

React 19.2 的第二个重大新特性是 Chrome 开发者工具中的性能跟踪功能。虽然活动跟踪有助于控制操作行为,但性能跟踪能帮助我们理解行为背后的原因。

此前进行性能调试时,我们不得不同时使用两个工具:React 开发者工具和性能时间轴。任何尝试过这种操作的人都知道,从中提取有价值的信息简直是超人般的任务。

现在,所有内容都清晰地呈现在单一时间线上:React事件、指标数据、网络请求、正在运行的JavaScript以及事件循环活动。这些内容被划分为清晰独立的子面板————轨迹。

调度轨迹

这展示了React当前的工作内容、优先级安排、渲染周期阶段的划分(更新、渲染、提交、剩余效果)以及各阶段耗时。它有助于理解React的工作原理,这对INP优化至关重要。

请密切关注级联更新。如果某个组件在渲染过程中触发了其他组件的更新,React就必须丢弃部分工作并重新开始,这显然会严重影响性能。

组件轨迹

大多数 React 性能问题并非源于组件本身“运行缓慢”,而是因为组件渲染频率远超必要。组件追踪器通过火焰图形式可视化呈现单个组件、渲染时长及相关效果。

这就像X光片,能揭示哪些组件对性能产生何种影响。你看到的每条"条带"都对应一个特定组件:

  • 渲染时长,
  • 暂停时长,
  • 创建子树的深度,
  • 以及是否包含持续时间可疑的持久效果。

服务轨迹

若您正在使用 React 服务器组件,也务必尝试全新的性能分析方法。新增的“服务器跟踪”面板可显示 Node.js 服务器端渲染过程中发生的调用和操作。这至关重要,因为在当今的混合应用中,部分逻辑在客户端运行,部分在服务器端运行,仅凭直觉判断已不再可行。

结论

React 仅仅是一种工具,其表现优劣完全取决于开发者掌握它的程度。借助全新的性能跟踪功能,你可以深入时间线进行分析,或许还能借助新推出的活动组件,让你的应用程序重现闪电般的速度!

想要了解更多?不妨关注已发布稳定版的 React 编译器,或是 React 团队在十月份大会上展示的所有内容