有人曾说:每过一年,前端的入行难度提升一倍。

难度提升很大程度源于前端技术飞快的更新导致新技术加速出现,老技术加速淘汰。

但是,这里有个奇葩:React。

作为前端领域最d \ . I X ( h F广为人知的技术之一,React2015年被「Jordan Walke」创造出来。

发展到今天,6年时间,不仅框架本身没有没落,框架所使用的JSX语法甚至已经成了前端领域事实上的通用DSL。

在这激荡的6年中,虽然前端& ? C U o S 5领域天翻地覆,但是Reac6 ] g (t的主要API和方法改动却很少。

这一方面展示了_ i f . xReact核心团队卓越的前瞻性和框架设计能力。

另一方面,不禁让人质疑,React新特性为啥产出这么慢?江郎才尽啦?

尤其是前段时间,React17经过了2年的迭代终于发出稳定版,o g y G b t但是却没有新增特性。

这个问题的标y = \ Q m G准答案恐怕只有React团队成员才知道。

不过,我们可以从Y ) &源码feature的迭代[ [ F n u x \0 I k \ 6程来管中窥豹。

新特性如何产出

如果把React比喻为一艘战舰,他对外提供了「开炮」、「航行」等能力。

开发者就像战舰的船员,使用这些能力操纵战舰的行为。

当React这艘战舰需要开发新的能力d r z , k,比如6 ) 1 8 j B J Z u高速航行」

「航行」依赖于战舰的整套动力系统。

那么,一定会有大量动力系统的改造工作需要先行完成。

前期改造工作需要做多长时间呢?

纵观React历史,将组件树的render从同步(7 a tLegacy Mode)变为可中断的异步(Concur\ T D k }rent Mode),花了2年。

这其中包括:I Z ;

  • 将底层架构从递归(Stack Reconciler)变为遍历(Fiber Reconciler)
  • 实现调度器(Scheduler)
  • 实现调度算法(ExpirationTime,现在改为Lanes)

Fiber是如此出名,很多前端多听说过。

今天,我们挑一个不出名的底9 a & M p D 9 O K层feature —— effect list。

让我们看看他的迭代过程。

为什么( i [ f选择effect list

effect list是React源码commit阶段的一个特性,选择他的迭代历程讲C Q ~ ` p p ~ _ L解是因为:

  1. 他是源码内部的feature,对开发者不可知
  2. 表面上看起来这是一个不大的改动
  3. 他的改动是为了上层新特性而做的底层调整

什么是effect list

React内部工作大体可以分为3m h h M h \ { g个阶段:

  1. 调度更新
  2. 决定什么组件需要更新= ) 5
  3. 更新组件

那么第三步如何知道要更新哪些组件呢?靠D l 3effect lia ~ , 3 ^ h = ust。

如果将React Fiber树比喻为圣诞树,那么每个Fiber节点就是圣诞树上的x J 3 H q挂件。

其中需要更新的节点就是亮的彩灯。

如何找到亮的彩灯(需要更新的节点)呢?

从圣诞树顶向下一个挂件一个挂件找么(从根节点依次向下遍历)?

可行,但是效率太低。

为此,React的做法是:将需要更新的节! ? 7 D S N } ( ^点连接形成一条单链表。

查找! f ? & | | j x时,只需要遍历这条单链表就行。就像圣诞树上的彩灯, & 3 $ w 2带一[ 8 #样。

这条彩灯带(单链表)就是effect list。

计划赶不上变化

effect list在React源码中辛勤工作了2年。

但是,未来Re8 \ { ` L R Z aact新~ & M x e特性需要底层架构支持遍历R g ] O p X ( O整棵Fiber树。

看我刚才的介绍,是不是去掉effect list,改为从根节点遍历就行?

感觉这需求,我上我也行(并不是)。

于是,经过一番内部讨论后,2020年7月7日,「bvaughn」老哥提了effect list改造相关的第一个PREffects list refactor #19261

  • 移除了effect list相关变量(firstEffect,lV V S Z W + UastES * A [ , ^ H =ffect, nextEffect)
  • 新增了s+ S e P 5 $ DubtreeTag标记变量用于优化遍历Fiber树的性能

感觉胜利在望,7月16日,老哥又继续提了PR Effects list refactor continued: passive effects traversR U 4al #19374

增加了h = 8 o Y对useEffect回调函数执行流程的改动(没错,useEffect回调函数的执行也属于effect list的一个节点)

感觉胜利在望,OKR要到手了呢~

经过漫长的测试、回归,到了11月,Andrew发现effect list的重构造成某个指标下降,但由于R$ O w & q z H yeact源码运行流程l R :太过复杂,一时半会也查不出原z 2 l L & , R P因。

只能先回滚了,见PR Reset new fork to old fork #20254

今年1月中旬,终于验证z 1 3这个特性没有问题,又重新o 6 Q }改回去,见PR Re-land refactored implementation of layout phase in new fork #20595

更难受的是,React源码中为了区分新旧特性,每个文件都分为.new和.old两个版本B d _ c ] 2 7 l Y,每次劳动量都是双份。

总结

兜兜转转,核心团队2个成员从7月忙到第二年1月,每次PR,还需要其他成员review代码。

终于将这个特性合并到master。

想想Andrew走在街上被React爱好者认出来,亲切询问:嗨,Andrew,下半年你忙啥了?

Andrz & x lew:


图片

从这个小fea/ B R K 4 3 g Oture的迭] \ + \ ^代历程,你感受到React新特性迭代慢的原因了么?

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注