当前位置: 首页 > 科技观察

为什么React新特性的输出这么慢?姜浪累死了吗?

时间:2023-03-15 15:10:11 科技观察

有人曾说过:每一年,进入前端行业的难度都会翻一番。难度的增加很大程度是由于前端技术的快速更新,导致新技术的加速出现和旧技术的加速淘汰。然而,这里有一个奇妙的东西:React。React作为前端领域最知名的技术之一,由“JordanWalke”于2015年创立,6年的今天,不仅框架本身没有衰落,框架使用的JSX语法也没有衰落甚至已经成为前端领域事实上的通用DSL。在这动荡的六年里,虽然前端领域天翻地覆,但React的主要API和方法变化却寥寥无几。这方面体现了React核心团队出色的前瞻性和框架设计能力。另一方面,不禁让人疑惑,为什么React的新特性出品这么慢?人才枯竭了吗?尤其是前段时间,经过两年的迭代,React17终于发布了稳定版,但是并没有什么新特性。这个问题的标准答案大概只有React团队成员知道。不过,我们可以从源码特征的迭代过程中窥见一斑。如何产生新特性如果把React比作一艘战舰,它提供了“大炮”、“航行”等外部能力。开发人员就像一艘战舰的船员,使用这些能力来操纵战舰的行为。React时,战舰需要开发新的能力,比如“高速航行”。而“航行”则取决于战舰的整个动力系统。那么,必然有大量的电力系统改造工作需要首先完成。前期改造工作需要多长时间?纵观React的历史,将组件树的渲染从同步(LegacyMode)转变为可中断异步(ConcurrentMode)用了2年时间。其中包括:将底层架构从递归(StackReconciler)改为遍历(FiberReconciler)实现调度器(Scheduler)实现调度算法(ExpirationTime,现在改为Lanes)Fiber太有名了,很多前端都听说过.今天,我们挑一个不为人知的底层特性——效果列表。我们来看看他的迭代过程。为什么选择效果列表效果列表是React源代码提交阶段的一个特性。选择它的迭代过程是因为:它是源代码的内部特征,开发人员不知道。从表面上看,这似乎是一个很小的变化。他的改动是针对上层新特性的Low-level调整。什么是效果表?React内部的工作大致可以分为三个阶段:调度和更新,确定哪些组件需要更新。那你怎么知道第三步要更新哪些组件呢?靠效果单。如果把ReactFiber树比作一棵圣诞树,那么每个Fiber节点就是圣诞树上的一个挂件。其中,需要更新的节点是亮色灯。如何找到亮色灯(需要更新的节点)?找到从圣诞树顶端到下一个吊坠的下一个吊坠(从根节点依次向下遍历)?可行,但效率太低。为此,React的做法是:将需要更新的节点连接起来,形成一个单向链表。查找的时候,只需要遍历这个单向链表即可。就像圣诞树上的灯串。这个彩色灯带(单链表)就是效果列表。计划赶不上变化。效果列表在React源码中努力了2年。但是React以后的新特性需要底层架构支持遍历整棵Fiber树。看我刚才的介绍,去掉效果列表,改从根节点开始遍历行不行?我感觉这个需求我可以完成(不是)。于是,经过一番内部讨论,2020年7月7日,“bvaughn”哥提出了第一个PREffects列表重构相关的效果列表改造#19261,去除效果列表相关变量(firstEffect,lastEffect,nextEffect),增加了一个subtreeTag标签变量优化遍历Fiber树的性能。我觉得胜利在望。7月16号老哥继续提PREffectslistrefactorcontinued:passiveeffectstraversal#19374添加了useEffect回调函数执行过程的改动(是的,useEffect回调函数的执行也属于effectlist的一个节点)感觉胜利在望,OKR即将获得~经过长时间的测试和回归,11月,Andrew发现重构效果列表导致某项指标下降,但由于React源码运行过程太复杂,一时半会找不到原因。只能先回滚,看PRResetnewforktooldfork#20254今年1月中旬,终于验证了这个feature没有问题,又改回来,看PRRe-landrefactoredimplementationoflayoutphaseinnewfork#20595More比较难受的是,React源码中为了区分新旧特性,将每个文件分为.new和.old两个版本,每次的工作量都是双倍的。综上所述,兜兜转转,核心团队的两位成员从7月一直忙到次年1月。每次PR,其他成员都需要review代码。最终将此功能合并到master中。想想安德鲁走在大街上,被React爱好者认出来,请问:嘿,安德鲁,下半年你在忙什么?Andrew:从这个小特性的迭代过程中,是否感受到React新特性迭代缓慢的原因??