【翻译】光速React – Vixlet
翻译原文链接:https://blog.vixlet.com/react-at-light-speed-78cd172a6411
个人翻译小站链接:http://www.zcfy.cc/article/react-at-light-speed-vixlet-2920.html
在过去的几年里, 我们Vixlet (http://www.vixlet.com) 的web团队,着手了一项激动人心的项目,将我们的整个web应用迁往React+Redux的建设。对于我们整个团队来说
这是一个不断增长的机会,而且在这个项目过程中,我们一直充满着挑战。
自此我们的web-app中,包含有几百甚至上千的媒体,文本,视频以及链接等内容,我们花了很长的时间去摸索关于react构建的方式,这里我们将分享一些踩过的经验。
声明: 讲解的这些经验和方法,已经能够很好的满足我们特殊应用的需求,然而,如果是整体开发的话,将你的应用和团队考虑其中至关重要,React的速度是相当快的,所以你可能没有必要很精确的了解到我们的使用场景,但是,我们希望你能发现一些发送的有益的信息。
基本原理
向更大的世界迈出一步.
The render() 函数
作为一个通用原则,尽量在render函数里面少做事,如果实在很有必要运行一些复杂的操作和计算,也许可以考虑将他们移到 memoized 函数里面, 这样得到的结果能够被缓存.了解 Lodash.memoize 关于 memoization函数的模型.
相反地,去避免更改巨大的,轻易计算的值在组件中的状态是很重要的。例如,如果props参数同时包含 firstName
和 lastName
,那么就没必要在state状态里面包含 fullName
,因为它很容易从props属性里面获得。 如果一个值能以一种很有效的方式通过props获得,通过使用通用的字符串连接,或者基本的的算法操作,那么我们就没必要更改状态来获取该值了。
Prop 和 Reconciliation
这是很重要的,记住React触发时,是会重新渲染的,其prop值(或者state状态)跟之前的值是不相等的。它包含了在嵌套组件,且其props和state包含对象或者数组之内的任何变化,记住这一点,这是很重要的情况,就是可能不经意的render循环,去创造prop或者state的值,就可能引起巨大的性能冲击。
例如: 函数绑定问题
例如: 对象或者数组的字面值
例如_: 注意fallback返回的值
尽可能的保证Props(和state)最小
一般来讲,props是在被需要的情况下,才会传递给一个组件,通过一个大且复杂的对象,或者很多个单独的props传递给组件,仅仅只是为了给其子组件传递值,但这会引起不必要的组件渲染(同时增加了开发的复杂性).
在我们Vixlet这边,我们使用Redux作为state的容器,因此在我们的这种情况,大部分是从react-redux中使用connect()函数,根据组件中的每一个等级去直接获取需要的数据。connect()函数是非常高性能并且占用的开销非常小。
组件方法
自从给每一个组件实列赋予了组件的方法,如果可以的,你要么使用纯粹的来自helper/util模板中的函数,要么使用静态类方法,这里有一个特别值得注意的地方,就是当有很大数字的组件在app里面进行渲染的时候。
高级
读完我的观点,jank变得邪恶了!
shouldComponentUpdate()
React生命周期中包含一个的方法 [shouldComponentUpdate()](https://facebook.github.io/react/docs/react-component.html#shouldcomponentupdate)
.这个方法可以告诉React,组件是否应该被渲染或者不依赖当前或者下一个props/state的值。
然而使用这个方法有个问题,那就是开发者必须仔细考虑每一种重新渲染发生的条件。这就使逻辑变得很复杂,通常来说,这太痛苦了,如果你真的需要它,那你就使用 shouldComponentUpdate()
方法,但是对于很多的情况,一般都有更好的选择。
React.PureComponent
React v15版本开始,其包含了 PureComponent类,可以用来建立组件。React.PureComponent
基本实现了它自己的shouldComponentUpdate()
方法,并且能够自动判断出当前以及下一个props/state组件之间的比较。如果想看更多的信息,请至Stack Overflow:
http://stackoverflow.com/questions/36084515/how-does-shallow-compare-work-in-react
在几乎所有的情况中,React.PureComponent
无疑是比React.Component
更好的选择.当创建一个新的组件时候,试着将其建立为一个纯粹的组件先,并且将组件功能引入,使用React.Component
.
更多信息: [React.PureComponent](https://facebook.github.io/react/docs/react-api.html#react.purecomponent)
官方React文档
组件运行分析 (in Chrome)
在最新Chrome版本,新增了一个建立时间表功能的工具,它可以将React组件渲染详细的信息,以及所花的时间显示出来。使用该功能只需要添加?react_perf
放在你想测试的url的后面即可。React渲染的时间列表数据,将会在用户时间部分之下显示。
更多信息: Profiling Components with Chrome Timeline官方React文档
有用的Utility: why-did-you-update
这是一个很好的NPM包,当没有必要重新渲染组件的时候,它能进行补丁,在console里面打印出来通知。
注: 这个模块能够使用过滤器进行初始化,去匹配特殊的你想要的组件,否则你的所有console出来的东西,都会被识别为垃圾信息,或者你的浏览器可能会崩溃,至 why-did-you-update docs获取更多细节信息。
常见的性能陷阱
setTimeout() and setInterval()
使用 setTimeout()
or setInterval()
在一个 React组件之中,需要极其的小心。这里几乎是更好的选择去使用 ‘resize’ 和 ‘scroll’ 事件 (注: 见下一章节需要注意的事项).
如果你需要使用 setTimeout()
or setInterval()
, 你必须 遵循下面几个禁令
极其短时间内持续发生不要使用
短时间内持续发生是没有必要使用的,特别是小于100ms的,如果更短的时间内,真的需要,也许你可以使用 [window.requestAnimationFrame()](https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame)
来代替.
参考这些取消/清除函数
setTimeout()
and setInterval()
都返回一个唯一的标识符,对于延迟函数,如果有必要可以对其进行取消操作。自从这些函数在全局范围内运行,他们不需要关心你的组件是否已经不在,它会直接导致报错或者停止运行。+
注: 这是真的对于window.requestAnimationFrame()
来说
最简单的解决这个问题的方案其实是使用 react-timeoutNPM包,它可以提供高阶组件,确保它能够自动使用上面提到的那个东西,它添加了包裹在组件的props中的setTimeout/setInterval等函数(特别感谢Vixlet开发者Carl Pillot 可戳这里进入)
如果你不希望引入一个依赖,并且想要用你自己的方案去解决这个问题,下面这些可能对你的会有帮助:
如果你在使用requestAnimationFrame()来控制动画循环,你可以使用很小的通知来进行类似的处理。
去抖和防流事件
一定程度上来说,正常的事件是极其迅速的,像”scroll”,”resize”.这是很明智的,去抖事件,特别是如果这些事件被解决的话,远远比那些极其基本的功能执行的好。
Lodash有[_.debounce](https://lodash.com/docs/#debounce)
方法. 这里依然是一个独立的[debounce](https://www.npmjs.com/package/debounce)
NPM包
“但是我真的需要scroll/resize/无论什么事件立即响应”
我曾经发现了一种模式可以以一种高性能的方式来解决这类事件响应问题,那就是使用 requestAnimationFrame()
来监听事件开始和结束的时间,然后, [debounce()](https://lodash.com/docs#debounce)
函数通过使用 trailing
选项来设置为 true
(这就意味着函数仅仅在节流函数结束之后才结束)来阻止监听这个值,看下面的例子
密集的CPU任务导致线程阻塞
毫无疑问,很多任务一起将会加强CPU的损耗,因此引起主要的渲染阻塞,一些例子包括非常复杂的数学计算,通过一个很大的数组进行迭代,通过使用File
api来进行渲染/覆写. 加密或者解密图像数据从`` object中.
如果在所有的情节当中,也许使用web搬运工,将其一些功能性的东西搬移到另外一个线程中会更好,因此,我们的主要渲染进程中能够顺利的进行。
阅读这些
MDN 文章: Using Web Workers
MDN 文档: Worker API
结尾
我们希望你已经发现上面这些有用的建议和信息。最后说一句,如果没有我们的Vixlet团队,上面这些技巧和提示方法是不可能被搜索出来,并且很好的运行的,他们真的是我工作以来,有幸接触到的一群非常优秀的团队伙伴。
在React之外进行升华,持续学习和练习,希望和你一起进步!
谢谢 Matt Lubner
【翻译】光速React – Vixlet的更多相关文章
- 光速 React
光速 React Vixlet 团队优化性能的经验教训 在过去一年多,我们 Vixlet 的 web 团队已经着手于一个激动人心的项目:将我们的整个 web 应用迁移到 React + Redux 架 ...
- 【翻译】React vs Angular: JavaScript的双向性
翻译原文链接:https://blog.prototypr.io/react-vs-angular-two-sides-of-javascript-b850de22b413 我的翻译小站:http:/ ...
- 翻译--Thinking in React
无聊翻译篇react入门文章,去年学习react时看了一遍,很不错的一篇文章. https://reactjs.org/docs/thinking-in-react.html 部分为意译,旨在让new ...
- Thinking in React
本文翻译自React的官方博客,详情请阅读原文. React非常适合构建组件化的应用,它注重高性能,因此组建的重用,项目的扩展都十分灵活,Facebook和instagram的不少商业项目使用了此框架 ...
- Cordova VS React Native 谁是未来? - b
对于原生native还是倍加推崇的,极佳的用户体验和性能让我学的如痴如醉,可是互联网这个世界可以用一句话可以总结:没有什么是不可能的.自从阿里淘宝天猫横空出世,它们教会了人们如何在网上购物,然后仿佛一 ...
- React Native 初识
Facebook 在 React.js Conf 2015 大会上推出了基于 JavaScript 的开源框架 React Native,本中文教程翻译自 React Native 官方文档. Rea ...
- Learning React Native笔记
React Native作为一个新事物,相关的资料还不多 官方的文档比较简单,缺少一些系统的例子 在对React Native的应用中,迫切的想学习一些别人的最佳实践.所以想通过看书系统的学习下 之前 ...
- React文档翻译 (快速入门)
翻译自react的大部分文档,方便自己查阅. 目录 生命周期 实例化 存在期 销毁期 state Do Not Modify State Directly State Updates May Be A ...
- 【转】React 常用面试题目与分析
作者:王下邀月熊链接:https://zhuanlan.zhihu.com/p/24856035来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 本文有一定概率为水文,怕 ...
随机推荐
- JS高级学习路线——面向对象进阶
构造函数进阶 使用构造函数创建对象 用于创建对象 其除了是一个函数之外,我们又称之为构造对象的函数 - 简称构造函数 function Product(name,description){ //属性 ...
- 一个可能让你记忆力飙升的软件 —— 这是一道填空(keng)题
本文题目的两个含义: 1.填上次挖的坑,将优化后的软件分享给需要的网友(下载链接附在文末): 还没有看过的网友可以先看看这篇文章: 一个可能让你记忆力飙升的软件 2.这个软件的本质其实就是生成各种填空 ...
- idea + mybatis generator + maven 插件使用
idea + mybatis generator + maven 插件使用 采用的是 generator 的 maven 插件的方式 ~ 1 pom.xml mybatis其它配置一样,下面是配置my ...
- 讨论LSTM和RNN梯度消失问题
1RNN为什么会有梯度消失问题 (1)沿时间反向方向:t-n时刻梯度=t时刻梯度* π(W*激活函数的导数)
- 移动端测试方案--sptt
sptt sptt是移动端UI自动化测试的一种解决方案,全称为special tool of test.sptt提供了一套测试解决方案,并使用命令行完成相关操作,最终可集成在各种后续的流程中. spt ...
- windows平台把UliPad添加到右键菜单
对.py文件支持右键用UliPad打开方式支持: 1.打开注册表(win+R,运行框输入regedit) 2.先对*.py文件进行设置.找到注册表目录HKEY_CLASSES_ROOT\Python. ...
- 利用伪元素和css3实现鼠标移入下划线向两边展开效果
一.思路: 将伪元素:before和:after定位到元素底部中间,设置宽度从0变成100%达到目的. 二.实现: 1.首先定义一个块状元素(行内元素没有宽高)并修改样式为一个背景色为浅灰色的矩形,设 ...
- XtraBackup 原理与安装
简介 XtraBackup(PXB) 工具是 Percona 公司用 perl 语言开发的一个用于 MySQL 数据库物理热备的备份工具,支持 MySQl(Oracle).Percona Server ...
- python13_day4
上周复习 1,python基础 2,基本数据类型 3,函数式编程 函数式编程.三元运行.内置函数.文件处理 容易出问题的点 函数默认返回值为none,对于列表字典,传入引用. 1 2 3 4 5 6 ...
- js 时间时间戳互换
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="C ...