为什么不用Preact或者Fast-React来代替React ?
Posted 腾讯IMWeb前端团队
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么不用Preact或者Fast-React来代替React ?相关的知识,希望对你有一定的参考价值。
1写在前面
生命在于折腾,Coder的折腾就在于造各种轮子。
React在前端圈大火之后,轮子层出不穷。而其中的一些轮子,由于专注于解决很多人诟病的React过大、过慢的问题(然而不并不觉得),也相当出名。关注最多的莫过于Preact、Inferno等以「轻量化」为特色的库了,Github Star数也超过10000。另外由于React广泛应用于同构应用上,并且 rendertoString
,renderToStaticMarkup
也存在同步执行、速度慢等问题,一些专注于React服务器端渲染的库也颇受关注。如Preact产出的preact-render-to-string还有我现在的团队在用的fast-react-render,都是这个思路。
然而我一直都不喜欢这些替代库,特别是在同构的场景下。
有以下几个简单的原因:
2原因
Checksum
React通过 renderToString
生成的DOM Content除了在每个节点上都有 data-reactid
属性外,在根节点上还生成了一个 checksum
的属性。浏览器端的React会在第一次render时校验节点内容与服务器生成内容的一致性,如果不一致则需要做很多DOM的增删改操作。理论上一致的checksum会节省大量javascript执行、Reflow时间(可查看Benchmark)。而preact-render-to-string、fast-react-render都没有加入checksum的逻辑。其生成的代码,不管前端使用Preact还是React,都需要将整个DOM树重渲染一次。
由于浏览器端的render也是同步的,意味这段重渲染的时间里是无法与页面交互的。
兼容性
Preact, Inferno并没有实现对React的100%兼容(即便使用了xxx-compat包)。姑且不论你可能无法使用React社区里无数针对React深度定制的包,你也无法使用大家都喜欢的ant-design。
不做过早优化
「程序员工具箱中最强大的优化技术就是不做优化。」——《Unix编程艺术》
可维护性
我个人最喜欢Facebook开源项目的一点是,他们的项目是真的用在了自己的核心产品上。不单依靠那些五花八门的测试用例、没有那些天花乱坠的推广软文,React的稳定性已经得到数十亿网民的验证。而且,Facebook在React 16还没有release的情况下已经在主站开始使用React Fiber,并通过完整的测试用例保证其向后兼容性,让React的使用者很安心。
而其他的项目,多为个人开发的项目。开源社区里过个一两年之后就停止维护的事情也是常有的,这些替代库的bug修复是否及时,是否能跟上React的更新节奏,我个人也是很持怀疑态度的。
面向未来
接上文的React更新节奏说起,React Team一直保持着高效、专注的产出,围绕着提升Web开发体验、表现性能等持续优化。Fiber在调度上做了相当多的优化,实际动画性能需要进一步了解,不过之前饱受诟病的 renderToString
、 render
的性能同时也得到了较大的提升(可以在Benchmark中看到),一下子拉近了和其他强调渲染性能的替代者的距离。
另外倍受关注的流式渲染也终于合并到主干了!我们之前甚至考虑过使用react-dom-stream来替换掉 ~renderToString~,这下可以直接使用官方的异步方案了。效果如何不好说,但起码增加了更多可能性。而同时Preact等并没有Stream方案。
再次,从优化的角度来看,框架都是在演化的。今天我们可以为了性能换上Preact,明天也许就要为了性能去换上Xreact。然而不管摩尔定律有没有失效,硬件、网络环境终归是在不断发展的,这些通过换库带来的一些体积、执行时间上的节省,半年、一年之后也许就微乎其微,而我们之前的工作也就没有任何意义。
3Benchmark
最后口说无凭,对React、React@15、Fast React、Preact做了一个benchmark。react-static是指调用 renderToStaticMarkup
时的数据。结果如下:
Server
- | fast-react | preact | react | react-static | react15 |
---|---|---|---|---|---|
1000 times | 3.00 | 4.00 | 7.00 | 3.25 | 7.75 |
200000 times | 311.00 | 443.00 | 557.00 | 297.50 | 805.50 |
可以看到React@16相比React@15已经提升了1/3,接近Preact的成绩了。
另外值得注意的是 renderToStaticMarkup
其实性能相当不错。如果你确定可以放弃checksum,希望寻找一个更快的服务器端渲染方式,不如直接使用 renderToStaticMarkup
。
你也可以clone https://github.com/raxjs/server-side-rendering-comparison 来对比React@16 & React@15,相信会得到类似的结论。
Client
Client是使用Chrome Headless模式来测试的。
Fast-React的浏览器端直接使用React@16来渲染。Preact的render方法因为默认是append行为,所以增加了一个preact-replace来和React行为做对比。
parse时长是调用 renderToString
, renderToStaticMarkup
, preact.render
方法的时间。load时间为 performance.timing.responseStart
到render结束后的时间。
React@16在浏览器端渲染性能提升了一倍多,成绩相当不错。而且得益于checksum的加持,如果checksum是一致的(react栏),React的渲染时间在DOM节点较少的时候与Preact一致,在节点很多的情况下比Preact、其他方案的成绩要好一大截。
而由于Preact体积的优势,在节点较少的情况下load时长相当短,相信在低速网络、低端设备下会有更好的性能表现。
其中还有一个有意思的一点,在200000节点的情况下,虽然React的render时间很短,但最后的load时间却不是最短的。自然是由于每个DOM节点上增加的 data-reactid
导致html下载、解析时间变长。不过React Team也考虑过彻底移除data-reactid,也许未来某个版本会得到修改,而那时直接使用React渲染同构应用将肯定是性能最佳的选择之一。
4小结
很兴奋React@16在性能方面做了这么多优化,相信绝大多数情况下我已经不用考虑其他的替代方案了。当然也有例外:
当你的目标用户网络环境比较糟糕时:之前的测试主要是基于执行速度来考察的。然而React毕竟有40多K,比起Preact还是要大不少。在开发m.uber里,提到了多次2G网络,我觉得也是影响Uber工程师选择Preact的关键因素。如果你的用户主要使用2G网络,可以考虑一些替代方案。(当然这也是违反我们「面向未来」的观点的,uber工程师也有可能也是为了替换Preact而找的理由……
从零开始一个项目,不喜欢React:这种情况下,请随意……
原文:http://imweb.io/topic/5955bdcc690607610fe2e96e
扫码下方二维码,
随时关注更多前端干货文章!
▼
微信:IMWebTech
以上是关于为什么不用Preact或者Fast-React来代替React ?的主要内容,如果未能解决你的问题,请参考以下文章