2161天!这就是React团队从计划为React添加并发渲染的能力,到发布可用版本的React18所用的时间。为什么中间花了这么长时间?中间发生了哪些有趣的故事?让我们回到2016年,回顾一下React并发渲染的诞生过程!今天的文章将以一种更加轻松的方式带大家领略整体演变过程。它不会涉及太多的技术性,而且会更容易阅读。相信看完这篇文章,再看前面的问题会有不一样的感觉。理解。浏览器的瓶颈早在2016年,React就已经在前端爆发了。React团队的目标一直是为数百万基于React构建的网站提供尽可能最佳的性能体验!但提升性能的最大瓶颈并不一定与React本身有关。相反,它与JavaScript、React所基于的语言以及JavaScript所在的浏览器环境有关。浏览器在一个主线程中处理所有JavaScript代码、用户事件、渲染、布局、绘画和回流。正常情况下,它们互不干扰,配合默契,但一不小心,就会出问题。ReactConf2018React现在是同步的,这意味着当你更新一个组件时,React同步处理这个更新,它会一直在一个主线程上工作,直到所有更新完成。所以问题是用户事件也在主线程上触发,如果React同时渲染更新并且用户尝试同步输入内容,React将等待所有正在执行的渲染在它之前完成可以处理用户事件。—ReactConf2018Fiber诞生多线程渲染那么,如果问题是渲染阻塞了主线程,难道我们不能在另一个线程中进行渲染工作吗?喜欢使用网络工作者?但实际上,这并不是React想要的。React想要的是一个解决方案,让当前的渲染工作更加灵活。ReactCong2017我们有一些IO工作,然后是一些CPU工作,理想情况下我们应该能够并行执行其中的一些工作。这不是性能问题,它基本上是一个调度问题。—ReactCong2017React团队发现他们可以通过区分低优先级和高优先级工作的方式来优化React。例如,用户输入和动画渲染是高优先级任务,它们赋予React在这些任务之间切换的能力。理论上,这样每一个React应用的体验都可以得到提升,因为React总是把最重要的工作放在第一位。这就是React团队最近正在做的事情,他们将其命名为ReactFiber。Fiber不是作为一个新框架发布的,而是作为一个主要的React版本发布的:React16。它使React异步和可中断。异步渲染在2017年初,React现在似乎更聪明了一些,它可以优先处理一些工作,并中断当前的渲染。然而,这种能力只能说是一个半成品,另外一件非常困难的事情是找到一个公共API,让React开发者能够以不完全破坏当前React生态系统的方式使用这些能力。解决这个问题的第一步是摆脱可能对新的异步可中断渲染功能产生副作用的部分。在新的架构中,一个组件的渲染分为两个阶段:第一阶段(也称为渲染阶段)可以被React打断,一旦打断,这个阶段所做的所有事情都会被丢弃,当React从处理紧急的事情,还是会重新渲染这个组件,这时候会重做第一阶段的工作。两个阶段的分界点是渲染函数。render函数之前的所有生命周期函数(包括render)都属于第一阶段。在React16.3中,如果我们在这些生命周期中引入副作用,重复执行,可能会给我们的程序带来不可预知的问题,所以在Reactv16.3中,React简单的引入了一个新的生命周期函数getDerivedStateFromProps,这个生命周期是一个静态方法,其中根本无法通过this访问当前组件,输入只能通过参数传递,对组件渲染的影响只能通过返回值传递。与此同时,React团队开始将这种新模式称为——异步渲染。ReactConf2018这里最大的问题不是性能,而是调度,所以我们不得不考虑调度,所以我们称这些新能力为异步渲染。我们的目标是让程序开发者能够适应设备和网络速度等用户限制,使交互体验更好。—ReactConf2018Hooks然而,一年后,dan继续说道:React缺少让调度更容易的东西,那就是Hooks。Hooks于2018年10月在Reactcomp中发布,这是React自发布以来最大的变化。Hooks最初的重点是它们让你以函数式的方式而不是类的方式创建React组件。但实际上,它们带来的好处更多。您可以更好地重用代码、组合和设置默认值。还有一点很重要,Hooks可以更自然的写出更兼容异步渲染的代码。.concurrentReact那么这个阶段我们也解锁了一个新名字:concurrentReact。ReactConf2018async是一个非常广泛的术语,可以描述很多,我们认为并发React是一个更合适的术语。concurrentReact可以同时处理多个任务,并根据这些任务的优先级在它们之间切换;它可以让渲染树做局部渲染而不需要将最终结果提交给DOM;而且,最重要的是,并发React不会阻塞主线程。——ReactConf2018并发模式然而,这种说法并没有持续多久,很快就会被并发模式所取代。事情到了2019年,终于有了可以用的东西,并发React正式更名为并发模式。ReactConf2019并发模式让React应用程序中断较大的低优先级任务,以专注于更高优先级的事情(例如响应用户输入事件)。—ReactConf2019并发模式现已进入实验模式—ReactConf2019来之不易,时隔三年,用户终于有东西可以用了。..但它是API的最终版本吗?不!它准备好用于生产了吗?不能!不过,并发模式让我们终于在程序中体验到了。我们可以在实验模式下开启它,这样我们就可以看到并发渲染的性能优势。但是,真的,这个想法很好,我们仍然受到升级策略的限制。升级策略React过去是无法在多个版本共存的,这意味着我们只能在一些DEMO项目和新项目中看到这种改进。如果我们想在现有的大型应用程序中使用它,我们需要一个更好的升级策略。React17就是为了解决这个问题而设计的,它在一年后的2020年8月发布。React17允许我们在同一个应用程序中允许多个版本的React,这允许我们在大型项目中采用增量升级策略,而你可以将部分程序升级到React18。然而,它在实践中并没有那么好用,因为增量升级策略不允许更精细的控制。React团队还提供了另一种模式,称为阻塞模式,它是旧模式和新并发渲染模式之间的混合模式。我应该怎么说呢?也是弱策略,没有达到预期的效果。React团队在后续阶段收到了大量的用户反馈。并发特性此时,距离React宣布开始新的架构已经过去了5年。在收到大量反馈后,React团队进行了修改。这一次,似乎要得出这个最终解决方案?ReactConf2021在听取了很多用户反馈后,我们很高兴地分享——并发模式在React18中消失了,取而代之的是逐步采用的渐进策略,您可以按照自己的节奏采用并发渲染。—ReactConf2021concurrentfeatures—顾名思义,因为不可能直接全面升级并发渲染,React希望给我们提供一些特性,让我们有选择地启用并发渲染。在这种模式下,您可以为应用程序的特定部分启用并发渲染。使用DeferredValue我们需要使用一些API来让我们能够在整个渲染过程中确定工作的优先级并且具有被中断的能力。首先,让我们看一下useDeferredValue,它允许我们标记特定状态的优先级。比如我们现在有这样一个场景。用户输入一些搜索关键词后,我们需要将搜索到的数据渲染成如下的细节。如果这个处理很耗时,连续的用户输入会感觉卡住了。其实我们希望的是用户的输入能够得到快速的响应,但是下面细节的渲染等一会也没关系。这时候我们可以通过useDeferredValue创建一个deferredText,真正的意思是将deferredText的渲染标记为低优先级,用户输入不会再有卡顿的感觉。startTransitionuseDeferredValue允许我们标记哪些特定状态具有较低的优先级,而startTransition可以明确告诉React哪些更新具有较低的优先级。当startTransition下包含一些更新时,React将处理那些优先级较低的更新,以支持用户输入等优先级较高的更新。悬念您可能经常听到的另一个词是悬念。它的目标是让读取React组件中的远程数据像使用props和state一样简单。是一个React组件,如果组件树的某些部分尚未准备好,它允许您以声明方式控制呈现的UI的某些部分。它允许我们将左边的代码简化为右边的代码,让你可以像React组件中的同步代码一样编写异步代码。React18是最终版本吗?React官方在官网提到,大多数情况下我们不会直接与这些并发渲染API进行交互,这让我们很难判断React18是否是一个革命性的版本。无论如何,这是我们等待了2000多天的巨大里程碑。你认为它是React中并发渲染的最终版本吗?
