React 性能优化

发布于 2022-04-22 12:36:44 字数 3926 浏览 965 评论 0

首先性能优化界有句经典的名言,叫「Measure/Profile first, optimise second」,意思就是先分析瓶颈,再进行优化。这是推崇数据先行的思路,理由是我们从理论上推导所知的性能瓶颈,不一定是真正的问题所在,因为在我们写的代码和实际在机器上运行的代码中间,还可能有编译器或框架本身会为我们做优化,这中间过程是不可见不可预测的。因此,先做 profile,从数据上看到性能瓶颈以后再进行优化,往往是比较高效的做法。

然后,程墨在 《浅出》 中引用了 Donald 的名言:「过早优化是万恶之源」并补全了原句,指出其实过早优化非架构上的、对性能影响不大的代码才是万恶之源,对核心代码的架构和性能进行优化是合理的,并且应该时时进行,越早越好,越到后面成本越高。至于什么算核心代码,大概没人能给出明确定义,只能依靠各人经验而为了。但他这里就指出了,经验(而非数据)在优化领域还是有用武之地的。

那么,以 React 为 UI 库的代码还有什么可优化的地方?不是说 React 的 diff 算法已经非常牛逼,reconciliation 已经非常高效了么?这是因为,React 只是个库(愿意的话也可叫框架),而没有任何库能完美契合 所有 使用者的需求。这就导致,为了保证绝大多数人的正常使用,它必须使用保守的设计策略,而不能假设每个开发者都具有比较丰富的背景知识。这个正确而保守的策略就为高级开发者带来了优化的空间。那么问题来了,你,是不是(是否愿意成为)这个高级的开发者呢?

React 组件的优化策略从大面上分列如下:

  • 避免不必要的 re-render
    • 定制 shouldComponentUpdate
    • 数组唯一的 key 属性
  • 避免不必要的数据计算
    • 纯净的副作用方案:reselect

避免不必要的 re-render

shouldComponentUpdate

这个方法是组件渲染前会被 React 询问的方法,如果返回 false,则组件不会被重新渲染。能否精准地控制这个方法的返回,是提升渲染、更新性能的重要因素。那么同学可能会有疑问,我写了几个月的前端代码,我们项目也没几个地方出现 shouldComponentUpdate 方法啊,难道这就说明我们项目的代码性能都不行吗?嗯,说对了一半。

待补。

数组唯一的 key 属性

避免不必要的数据计算

使用 reselect

经过一段时间使用发现,reselect 简直是 redux 项目的标配。如果你的 mapStateToProps() 中都仅是非常简单的从 store 中挑值,那当我没说,你很大概率不需要 reselect。但假如有以下的场景,那么几乎可以肯定 reselect 会是一个很好的方案:

  • mapStateToProps 中存在数据计算,你需要缓存以提升性能
    • 增删数据结构
    • 从已知数据计算状态
  • mapStateToProps 中存在数据结构变换,通常因为前端 view 需要的数据不是 redux 原始的数据结构
    • 实战场景1:章节分页
    • 实战场景2:建立索引
  • 需要将 mapStateToProps 封装一层,以达到 隔离组件与数据结构(redux 数据结构变化仅影响 reducer 和 selector)建立统一数据获取逻辑(同一段数据获取逻辑可以被多个组件复用) 等目的

其他方案

  • render 中计算差异 - 这样每次可能都会重新计算。然后又需要在 render 中引入 memoize
  • 将关联计算放在 reducer 并将算完的数据放到 redux - 这样 redux state 树会出现数据冗余。数据冗余有什么不好呢?维护一致性有成本和风险、可能不想级联修改

其他问题

用上 reselect 以后你可能会发现另一个问题,就是当你一份同样的 reducer 逻辑需要给多个组件使用时,你需要一个机制来区分。很多时候这个机制就是 const mapStateToProps = (store, ownProps) => ({})。好,这个机制可能会有问题,因为 ownProps 可能会一直变,导致 selector 多次重复计算,失去其缓存的优势。

问题的本质在于,ownProps 共享的不只是 reducer 核心逻辑,还需要有各自独立的数据结构,而 reselect 不能提供各自独立的缓存层,它只有一层。所以不仅需要一套机制共享 reducer 逻辑,还需要另一套机制,提供互相隔绝的数据缓存层。解决方案:

参考资料

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

JSmiles

生命进入颠沛而奔忙的本质状态,并将以不断告别和相遇的陈旧方式继续下去。

0 文章
0 评论
84961 人气
更多

推荐作者

醉城メ夜风

文章 0 评论 0

远昼

文章 0 评论 0

平生欢

文章 0 评论 0

微凉

文章 0 评论 0

Honwey

文章 0 评论 0

qq_ikhFfg

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文