原文地址: Web Performance Calendar » 5 tips to effectively optimize INP in React

1)减少DOM大小

确定 DOM 的大小并对其进行优化是一项基本要求。如果 DOM 太大(元素太多或嵌套太深),则可能会降低性能、减慢渲染速度并增加内存负载。

在 React 中,这个建议更加正确。更少的元素意味着更少的组件,这意味着需要下载和处理的 JavaScript 更少。

可以通过 Google Chrome 控制台快速验证 DOM 大小。只需输入脚本document.querySelectorAll("*").length,您便知道所处的位置。


控制台显示找到的 DOM 元素数量为 5,132。这个数量相当多。

Google建议DOM 元素的最大数量为 1,400 个。这个限制相当严格,尤其是对于电子商务或应用等大型网站而言。根据我们的经验,浏览器仍能快速处理 2,500 个 DOM 元素。一旦 DOM 元素数量超过此限制,事情就会迅速变得复杂。

2)将组件分为简单版本和扩展版本

即使组件或其内容对于 SEO 或可访问性很重要,也并不意味着它在首次呈现时必须具有完整的视觉质量。尤其是当组件在第一个视口中不可见时。

用户实际上会看到多少个组件?其中一些隐藏在交互后面,例如超级菜单或模式窗口,其他组件在滚动后可见。最终形式是否真的需要 HTML 中的所有组件?

通过拆分为简单而丰富的组件进行优化对于页面上多次重复的元素特别有效。这些通常是着陆页、产品列表或其他产品,就像您在图片中看到的那样:


页面加载时仅提供 SEO 相关数据的组件示例。此状态对用户而言是隐藏的。通过在视口中显示组件可激活“丰富变体”。

3)使用<Suspense>

<Suspense>标签主要用于React中不同组件加载过程中显示占位符内容。

然而,很少有人知道,它的隐藏功能<Suspense>是开启选择性渲染。这允许将页面及其组件划分为重要部分和不太重要的部分。


使用标签来分割组件树<Suspense>。红色组件被此标签标记为不太重要。

在使用SSR(服务端渲染)的时候,标签的效果<Suspense>绝对至关重要。

Hydration是服务器端生成的代码在浏览器客户端复活的时刻。服务器提供用户可快速看到的 HTML,然后 React 添加交互性。如果不使用<Suspense>,它总是一项漫长的 javascript 任务。

将页面分成单独的逻辑单元并将它们包装在自己的<Suspense>标签中。


booking.com 网站分为独立的逻辑单元。

但要小心!使用 标签也可能适得其反。如果用户快速对 中的元素执行操作<Suspense>,React 必须切换焦点并处理整个块。否则,它就不知道用户到底做了什么。这会导致同步处理,从而延长整个事件。

因此,切勿用此标签包裹大块,而应仅包裹较小的部分 - 部分。同时,不要将其<Suspense>用于第一个视口中可见的元素。

4)注意补水错误

我们已经解释了什么是 hydration。但我们还没有提到一件重要的事情。在 hydration 结束时,将执行验证,将生成的元素树 (DOM) 与来自服务器的状态进行比较。HTML 必须与 React 在客户端的期望完全匹配。

如果这些版本之间存在差异,React 会在浏览器控制台中抛出错误:


在浏览器控制台中显示水化错误。

此时,React 可能会使页面上的所有或大多数组件无效,并通过客户端 JavaScript 触发它们的更新,这会通过延长水化阶段来降低性能,并且可能会令人烦恼地延迟LCP指标。

更糟糕的是,你很容易陷入这个错误。例如,在服务器和客户端渲染时直接使用Math.random()Date.now()可能会导致内容不相同。

5)注意 useEffect()

useEffect在 React 中有一个特殊的函数,它只做一件事。对组件或其状态的变化做出反应。

根据定义,这是一个在发生变化后调用的函数。React 开发人员通常认为该函数甚至在 HTML 渲染后也会被调用。

不幸的是,事实并非如此。它useEffect 并不总是异步的。当用户调用输入(例如,点击)时,所有 React 代码都是同步执行的,包括“效果钩子”。

如果使用钩子来实际推迟作业直到下一个渲染周期,则必须使用setTimeout或其他方法