为什么不用Preact或者Fast-React来代替React ?

Posted 腾讯IMWeb前端团队

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么不用Preact或者Fast-React来代替React ?相关的知识,希望对你有一定的参考价值。

戳蓝字“IMWeb前端社区”关注我们哦!


1写在前面


生命在于折腾,Coder的折腾就在于造各种轮子

React在前端圈大火之后,轮子层出不穷。而其中的一些轮子,由于专注于解决很多人诟病的React过大、过慢的问题(然而不并不觉得),也相当出名。关注最多的莫过于PreactInferno等以「轻量化」为特色的库了,Github Star数也超过10000。另外由于React广泛应用于同构应用上,并且 rendertoStringrenderToStaticMarkup 也存在同步执行、速度慢等问题,一些专注于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 , renderToStaticMarkuppreact.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 ?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Preact 中使用 useEffect?

PSAT V.S. PreACT

前端资讯重磅升级!Preact X 发布!

Preact X 有什么新功能?

Preact:一个备胎的自我修养

preact 源码学习:JSX解析与DOM渲染