翻译原文链接: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的更多相关文章

  1. 光速 React

    光速 React Vixlet 团队优化性能的经验教训 在过去一年多,我们 Vixlet 的 web 团队已经着手于一个激动人心的项目:将我们的整个 web 应用迁移到 React + Redux 架 ...

  2. 【翻译】React vs Angular: JavaScript的双向性

    翻译原文链接:https://blog.prototypr.io/react-vs-angular-two-sides-of-javascript-b850de22b413 我的翻译小站:http:/ ...

  3. 翻译--Thinking in React

    无聊翻译篇react入门文章,去年学习react时看了一遍,很不错的一篇文章. https://reactjs.org/docs/thinking-in-react.html 部分为意译,旨在让new ...

  4. Thinking in React

    本文翻译自React的官方博客,详情请阅读原文. React非常适合构建组件化的应用,它注重高性能,因此组建的重用,项目的扩展都十分灵活,Facebook和instagram的不少商业项目使用了此框架 ...

  5. Cordova VS React Native 谁是未来? - b

    对于原生native还是倍加推崇的,极佳的用户体验和性能让我学的如痴如醉,可是互联网这个世界可以用一句话可以总结:没有什么是不可能的.自从阿里淘宝天猫横空出世,它们教会了人们如何在网上购物,然后仿佛一 ...

  6. React Native 初识

    Facebook 在 React.js Conf 2015 大会上推出了基于 JavaScript 的开源框架 React Native,本中文教程翻译自 React Native 官方文档. Rea ...

  7. Learning React Native笔记

    React Native作为一个新事物,相关的资料还不多 官方的文档比较简单,缺少一些系统的例子 在对React Native的应用中,迫切的想学习一些别人的最佳实践.所以想通过看书系统的学习下 之前 ...

  8. React文档翻译 (快速入门)

    翻译自react的大部分文档,方便自己查阅. 目录 生命周期 实例化 存在期 销毁期 state Do Not Modify State Directly State Updates May Be A ...

  9. 【转】React 常用面试题目与分析

    作者:王下邀月熊链接:https://zhuanlan.zhihu.com/p/24856035来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 本文有一定概率为水文,怕 ...

随机推荐

  1. 自然梯度(Natural Gradient)

    自然梯度(Natural Gradient)

  2. JVM知识在离线数据中的运用

    又是飞花的季节了.多愁善感的林妹妹看到柳絮说:“嫁与东风春不管,凭尔去,忍淹留.”宝姐姐看了却来一句:“好风凭借力送我上青云”. 特别羡慕情商高的人,经常在想他们是怎么做到的.从来看不出他们不喜欢谁, ...

  3. 连接greenvpn 公司内网连接

    查看计算机路由表 Route print 跟踪路由表 Tracert ip or dnsname 本次需求,连接greenvpn之后,公司10.130.41.** 网段的机器无法使用.本机ip 10. ...

  4. 腾讯云安全:开发者必看|Android 8.0 新特性及开发指南

    欢迎大家关注腾讯云技术社区-博客园官方主页,我们将持续在博客园为大家推荐技术精品文章哦~ 背景介绍 谷歌2017 I/O开发者大会今年将于5月17-19日在美国加州举办.大会将跟往年一样发布最新的 A ...

  5. Oracle自动备份.bat 最新更新(支持Win10了)

    20170418更新: 很多年没有用了,最近两天打开来用,发现在Win10下面At命令已经被淘汰不能使用了,还有不少命令工作方式和原来也不一样了 所以就更新了一下下,使用 schtasks 命令代替了 ...

  6. ue4构建光照失败问题与解决

    不知从哪天开始,我的ue4.13就突然无法成功构建光照了, 症状为:虽然swarm连接到了100%,然而之后就卡住一动不动,一看看log是连接tcp什么agent什么失败的. 虽然把所有物体都设置成非 ...

  7. 【Spark2.0源码学习】-4.Master启动

         Master作为Endpoint的具体实例,下面我们介绍一下Master启动以及OnStart指令后的相关工作   一.脚本概览      下面是一个举例: /opt/jdk1..0_79/ ...

  8. [转]Installing Memcached on Windows

    Installing Memcached on Windows 原文链接https://commaster.net/content/installing-memcached-windows   Sub ...

  9. Html5浏览器支持

    HTML5 浏览器支持 把 HTML5 元素定义为块级元素 语义块级displayblock实例 header, section, footer, aside, nav, main, article, ...

  10. 【国家集训队2012】tree(伍一鸣)

    Description 一棵n个点的树,每个点的初始权值为1.对于这棵树有q个操作,每个操作为以下四种操作之一:  + u v c:将u到v的路径上的点的权值都加上自然数c:  - u1 v1 u2 ...