高性能 react:3种加快应用程序的新工具
react 通常很快,但很容易造成导致性能问题的小错误。缓慢的组件安装,深层组件树和不必要的渲染循环可以快速添加到一个感觉缓慢的应用程序。
幸运的是,有很多工具,有些甚至内置于 React,这有助于诊断性能问题。在这篇文章中,我将强调使 React 应用程序更快速的工具和技术。每个部分还有一个互动,(希望)有趣的演示!
工具#1:性能时间表
React 15.4.0引入了一个新的性能时间轴功能,可让您准确了解组件的挂载,更新和卸载。它还可以让您可视化相关的组件生命周期。
注意:现在,此功能仅适用于Chrome,Edge和IE,因为它利用了尚未在所有浏览器中实现的用户时间轴API(User Timing API)。
怎么运行的
- 打开你的应用程序并附加查询参数:
react_perf
。例如,http://localhost:3000?react_perf
- 打开Chrome DevTools 性能选项卡,然后按 记录(Record)。
- 执行您要分析的操作。
- 停止记录
- 在
User Timing
下检查可视化。
了解输出
每个彩色条显示组件正在做“工作”的时间。由于JavaScript是单线程的,每当组件正在加载或呈现时,它会阻止主线程,并阻止其他代码运行。
方括号中的文字[update]
描述了组件生命周期的哪个部分正在发生。时间轴会分解每个步骤,因此您可以在[componentDidMount]
[componentWillReceiveProps]
[ctor]
(构造函数)和 [render]
方法上看到细粒度的时序.
堆叠的条表示组件树。虽然在React中具有相当深的组件树是典型的,但如果要优化经常安装的组件,则可以帮助减少封装组件的数量,因为每个组件都会增加小的性能和内存损失。
这里有一点值得注意的是,时间表中的时间序列是用于开发构建React的,它比生产环境更慢。事实上,甚至性能时间表本身会减慢您的应用程序。虽然这些数字不应该被认为是真实表现的性能,但是不同组件之间的相对定时是准确的。此外,组件是否更新完全不依赖于生产环境上的构建。
演示#1
为了乐趣,我操纵了TodoMVC应用程序,出现一些严重的性能问题。你可以在这里试试看。
要查看时间轴,请打开Chrome开发工具,转到“性能”选项卡,然后单击记录。然后在应用程序中添加一些TODO,停止录制并检查时间轴。看看是否可以发现哪些组件导致性能问题:)
工具#2:为什么更新
影响 React 中性能的最常见问题之一是不必要的渲染循环。默认情况下,即使他们的 props 没有改变,React 组件将在父级 render 时重新 render。
例如,如果我有一个这样的简单组件:
class DumbComponent extends Component {
render() {
return <div> {this.props.value} </div>;
}
}
加上父组件:
class Parent extends Component {
render() {
return <div>
<DumbComponent value={3} />
</div>;
}
}
无论何时父组件 render,DumbComponent
都会重新 render,尽管其 props
没有改变。
通常,如果 render 运行,并且没有对虚拟DOM进行任何更改,则这是一个浪费的渲染循环,因为该 render 方法应该是纯的,并且没有任何副作用。在大规模的 React 应用程序中,检测发生这种情况的地方可能很棘手,但幸运的是,有一个可以帮助的工具!
使用 why-did-you-update
why-did-you-update
是一个挂接到 React 的库,并检测潜在的不必要的组件渲染。它检测组件的render方法何时被调用,尽管它的 props
没有改变。
建立
安装 npm: npm i --save-dev why-did-you-update
在您的应用程序的任何地方添加此代码段:
import React from 'react'
if (process.env.NODE_ENV !== 'production') {
const {whyDidYouUpdate} = require('why-did-you-update')
whyDidYouUpdate(React)
}
请注意,此工具在本地开发中非常出色,但确保在生产中已被禁用,因为它会减慢您的应用程序。
了解输出
why-did-you-update
监视您的应用程序运行并记录可能会不必要地更改的组件。它允许您在渲染循环之前和之后看到 props
,确定它可能是不必要的。
演示#2
为了演示why-did-you-update
,我将库安装在 TodoMVC 应用程序的 Code Sandbox 上,这是一个在线 React 游戏场。打开浏览器控制台并添加一些 TODO 以查看输出。
请注意,应用程序中的几个组件不必要地 render。尝试实现上述技术来防止不必要的渲染。如果正确完成,则
why-did-you-update
控制台中不应有输出。
工具#3:反应开发工具
React 开发者工具 Chrome 扩展程序具有可视化组件更新的内置功能。这有助于检测不必要的渲染循环。要使用它,首先请确保在此处安装扩展。
然后,点击Chrome DevTools中的“React”标签打开扩展程序,然后选中“Highlight Updates”。
然后,只需使用你的应用程序。与各种组件交互,并观看 DevTools 工作的魔力。
了解输出
“react 开发人员工具”突出显示在给定时间点重新呈现的组件。根据更新的频率,使用不同的颜色。对于频繁更新的组件,蓝色显示不频繁更新,按更新频率依次为绿色,黄色和红色。
看到黄色或红色不一定是坏事。当调整滑块或触发频繁更新的其他UI元素时,可以预期。但是,如果您点击一个简单的按钮并看到红色,这可能意味着某些东西是错误的。该工具的目的是发现不必要的更新的组件。作为应用程序开发人员,您应该有一个一般的想法,哪些组件应该在给定的时间更新。
演示#3
为了演示组件突出显示,我安装了 TodoMVC 应用程序来不必要地更新某些组件。
打开上面的链接,然后打开 React Developer Tools 并启用更新突出显示。当您输入顶部文本输入时,您将看到所有 TODO 都不必要地突出显示。当您输入更快时,您将看到颜色更改以指示更频繁的更新。
修复不必要的渲染
一旦识别出应用程序中不必要的重新渲染的组件,就会有一些简单的修复。
使用PureComponent
在上面的例子中,DumbComponent
是它 props 的纯函数。也就是说,该组件只有在其 props
更改时才需要重新 render。React 有一种内置的特殊类型的组件,PureComponent
这个类型是为这个用例准备的。
而不是继承自 React.Component
,请使用 React.PureComponent
,如下所示:
class DumbComponent extends PureComponent {
render() {
return <div> {this.props.value} </div>;
}
}
然后,该组件只有在其 props
实际更改时才会重新 render。而已!
请注意,PureComponent
做一个 props
的浅比较,所以如果你使用复杂的数据结构,它可能会错过一些 props
更改,而不是更新您的组件。
实现 shouldComponentUpdate
shouldComponentUpdate
是 render 任何一个 props
或 state
更改之前调用的组件方法。如果 shouldComponentUpdate
返回 true
,render 将被调用,如果它返回 false
,没有任何反应。
通过实现此方法,您可以指示 React 避免重新渲染给定的组件,当其 props
不更改的时候。
例如,我们可以像下面这样,在一个组件中实现一个 shouldComponentUpdate
:
class DumbComponent extends Component {
shouldComponentUpdate(nextProps) {
if (this.props.value !== nextProps.value) {
return true;
} else {
return false;
}
}
render() {
return <div>foo</div>;
}
}
调试生产中的性能问题
如果您在自己的机器上运行应用程序,“React Developer Tools”才能起作用。如果您有兴趣了解用户在生产中看到的性能问题,请尝试使用LogRocket。
LogRocket 就像是网络应用程序,记录 DVR 字面上 的一切,您网站上发生的。您可以使用错误或性能问题重播会话,而不是猜测为什么会出现问题,以快速了解根本原因。
LogRocket 为您的应用程序记录性能数据,Redux actions/state,日志,错误,网络请求/响应与标题+主体和浏览器元数据。它还在页面上记录HTML和CSS,重新创建即使是最复杂的单页应用程序的像素视频。