为什么尤雨溪说react的性能不如vue?

Posted SHERlocked93

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么尤雨溪说react的性能不如vue?相关的知识,希望对你有一定的参考价值。

作者是前Facebook/Meta前端工程师,也是近4000颗星react-native-web的作者。 

此文摘自Andy Lee:React Turbo - React Forget 殺手[1]

React Turbo - React性能的最终救星

道歉一下,我原文中把react-native-webrtc[2]写成react-native-web,若有误会的读者,质疑我一次我道歉一次。

先讲结论,React Forget救不了React,React再不转向以subscription(订阅式响应)为主的reactivity响应,还固守comparison(比较式响应),迟早会被Solidjs、Svelte甚至是Vue干掉。

React之殇

React千好万好,只有一点不好:开发者需要自己确保性能。

不知道各位React开发者有没有想过,为什么有useMemo, useCallback, React.memo这些API,甚至useContext这个原本是用来放store, theme这种全局(considered “global” for a tree of React components)[3]的hook也被拿来提升性能,而最近的useEvent也几乎只是为了性能才增加。最惨的是就算用了这些方案,依然解决不了React的性能问题。

这才导致最近三年在redux, mobx后,居然还能出现引起浪潮的Recoil, zustand, jotai状态管理框架,而他们毫无例外都是subscription-based reactivity(订阅式响应)。

Subscription reactivity 订阅式响应 vs. Comparison reactivity 比较式响应

举个栗子,有一个text状态在组件A,组件A把text传给组件B,组件B把text传给组件C,以此类推,组件Y把text传给组件Z,最后组件Z上的。

function A() 
  const [text, setText] = useState(''');
  return <B text=text />

function B(text) 
  return <C text=text />;

// ...
function Z(text) 
  return <input value=text />;

当text变化时,组件A,B,C,D...到Z全部都会re-render重新渲染,而这是Comparison reactivity 比较式响应永远都避免不了的。

而Solidjs、Svelte, Vue甚至Angular会说:啊?为什么A到Z都要重新渲染?只要Z甚至只要这个input渲染就好啦

这时候你或许会说,用Context啊!然而就像Recoil介绍的视频[4]说的,当text不是一个,而是一个数组或nested的值时,Context是帮不上忙的。

Comparison reactivity 比较式响应的问题

只要React继续固守比较式响应,那

  1. React永远都达不到 fine-grained reactivity(细粒度响应)。

  2. 为了避免父组件们,与同组件内部的无关的value(值)与element(元素)被重複但无意义计算,都需要memoize(compare to return cached or new value)。

function Todo(todos, showDone, text) 
  const filteredTodos = todos.map(todo => todo.done === showDone);
  return (
    <div>
      <ul>filteredTodos.map(todo => <li>todo.task</li>)<ul>
      <input value=text />
    </div>
  )

有人可以解释:为什么text变化时,filteredTodos要重新计算呢? 你可能会回:加个useMemo就好啦!(依然有compare的无意义消耗)

那为什么<ul>...</ul>要回传新的React.createElement ,然后会造成Virtual DOM要重新但无意义比较呢? 你可能会回:Virtual DOM很快的。

然而<ul>...</ul>通常不是一个元素,而是一群组件,而这样组件又有包含一群组件。而他们的value和element 都必须重新创建,然后通常都很幸运的被浅比较,就发现相同,所以不会回传新值或去改真的DOM。

然而这些overhead消耗,

  1. 在大型或深deeply nested元素网页

  2. 有长list或table

  3. 输入是高频率,如text input文字输入、slider/range input拖动输入,或是如React Forget展示的color picker拖动式颜色输入,动辄每秒30-100ms一个event

已经证明,原本看来是微不足道的comparison overhead消耗,已经真正影响性能,使用者介面会有可体验的延迟。

然而,这些overhead消耗,在Subscription reactivity订阅式响应压根不需要考虑,因为订阅式响应就是指哪打哪,无关数值的创建和比较压根不会发生

React Turbo

React Turbo是一个babel plugin。

https://github.com/oney/react-turbo[5]

  1. 会在compile time编译时把react组件中的值,从普通的javascript值,包一层成为可观察/可订阅observable/subscribable的signals/atoms,就像是mobx, recoil, solidjs的state

  2. 并且以element为单位(而非component为单位)来订阅这些值。

  3. 理论上可以达到跟solidjs[6] 同等级的响应速度和低消耗。並且依然是immutable values相容於concurrent mode。

并且最重要的一点是,开发者完全不需要改动现有的代码,编译器会do the magic。

你可能好奇,为什么我说了这么多,现在才提到标题中的React Turbo?

虽然说React Turbo目前可运作(但有bug要修),但要真正达到最高性能,需要React核心有所改动来配合。再说我一个普通的开发者,没有利益,也不该是我的责任去优化React。

React Turbo比较是一个proof of concept,告诉React team:React变成真正的Subscription reactivity 订阅式响应是可能的。

未來

你敢想像一个没有useMemo, useCallback, React.memo, useEvent,甚至不需要写reselect的createSelector,也不需要再学乱七八糟mobx, recoil, zustand的世界吗?

React有过他辉煌的岁月,就像Facebook曾经很酷,Jquery曾经很酷,React曾经很酷过,但他现在老了落后了。

React再不革新,虽然最终慢慢死去,但在这过程中会继续折磨著因为生态、工作、已有代码而留存的开发者。

给自己一次机会吧,React。一个深爱React五年以上的coder笔。

参考资料

[1]

Andy Lee:React Turbo - React Forget 殺手: https://zhuanlan.zhihu.com/p/530458257

[2]

react-native-webrtc: https://github.com/react-native-webrtc/react-native-webrtc

[3]

(considered “global” for a tree of React components): https://zh-hant.reactjs.org/docs/context.html#when-to-use-context

[4]

Recoil介绍的视频: https://www.youtube.com/watch?v=_ISAA_Jt9kI

[5]

https://github.com/oney/react-turbo: https://github.com/oney/react-turbo

[6]

solidjs: https://www.zhihu.com/search?q=solidjs&search_source=Entity&hybrid_search_source=Entity&hybrid_search_extra=%7B%22sourceType%22%3A%22answer%22%2C%22sourceId%22%3A2533826292%7D

最后

如果你觉得这篇内容对你挺有启发,我想邀请你帮我个小忙:

  1. 点个「喜欢」或「在看」,让更多的人也能看到这篇内容

  2. 我组建了个氛围非常好的前端群,里面有很多前端小伙伴,欢迎加我微信「sherlocked_93」拉你加群,一起交流和学习

  3. 关注公众号「前端下午茶」,持续为你推送精选好文,也可以加我为好友,随时聊骚。

点个喜欢支持我吧,在看就更好了

以上是关于为什么尤雨溪说react的性能不如vue?的主要内容,如果未能解决你的问题,请参考以下文章

尤雨溪说,不会用vue.js这些要点,你永远也无法撑握vue

React 和 Vue 到底谁更牛?听听尤雨溪怎么说

尤雨溪回应:Vue与TypeScript为什么相性特别差?

Vue.js 作者尤雨溪加盟 Weex 团队担任技术顾问

尤雨溪:Vue.js 3.0 计划

尤雨溪官宣 Vue 3.2 已发布