找回密码
 会员注册
查看: 27|回复: 0

ReactConcurrentMode初识&探秘

[复制链接]

3

主题

0

回帖

10

积分

新手上路

积分
10
发表于 2024-9-20 18:14:33 | 显示全部楼层 |阅读模式
今天的文章来得晚了一点,就是为了等这个视频,给我们自己的大会做个小推广~腾讯TWeb前端技术大会,将于10月24日9点正式举办!线上直播票限时优惠进行中,请点击下方视频内链接报名参会,了解业界领先技术方向与实践,一起跟大厂技术大咖交流~1.引言在使用 React 之前,不知道小伙伴们有没有遇到过 更新卡顿 的问题,如下为 React 应用更新时的火焰图,JS执行287ms后,渲染任务才开始(25.4ms)。主流浏览器刷新频率为 60Hz,即每16.6ms浏览器刷新一次,每16.6ms要完成JS执行、重绘重排。而JS线程和GUI线程是互斥的,在浏览器的一帧里(16.6ms)JS脚本执行和页面渲染是同步执行的,一旦JS脚本执行时间过长,页面就会出现掉帧卡顿。为了减少JS脚本执行的时长,React 重写了架构来解决卡顿问题。2.React架构重写2.1.React16之前的架构(图摘自ReactConf2017LinClack的 Live)reconciler:调和(也叫协调)器。协调可以理解为:将以虚拟形式存在的VDOM与真实DOM同步的一个过程(React官方对 reconciler 的解释更偏向于源码角度)。所以协调器的一个核心就是diff,React15 的协调也叫栈调和(Stackreconciler)。renderer:渲染器。React 组件发生更新时,调和器通知渲染器将变化的VDOM重新渲染到页面。2.2.React16架构(Fiber架构)React16 重写架构解决卡顿问题。上文提到,JS线程和GUI线程是互斥的,所以在浏览器的一帧里(16.6ms)JS脚本执行和页面渲染是同步执行的,一旦JS脚本执行时间过长,页面就会出现掉帧卡顿。而 React15 组件的挂载和更新都采用递归更新,一旦vDOM嵌套层次很深,页面就会出现比较严重的卡顿。(同步渲染,图摘自ReactConf2017LinClack的 Live)那如何解决这个问题呢?有篇文章 《理解ReactFiber&ConcurrentMode》 通过类比 HTTP 队头阻塞,很好地解释了解决这个问题的原理。HTTP 队头阻塞的根本原因在于,HTTP 基于 请求-响应 的模型,在同一个TCP长连接中,前面的请求没有得到响应,后面的请求就会被阻塞。HTTP/2 提出了通过 二进制分帧 来解决这个问题,原来Headers+Body的 HTTP 报文格式,被拆分成一个个的二进制帧,这些帧在TCP管道里没有先后顺序,服务器接收到的帧可以是乱序的,因此就解决了排队等待导致的阻塞问题。React 的卡顿问题和 HTTP 队头阻塞问题的本质是一样的,无法简单地通过提高CPU计算速度来解决。解决这个问题的答案,就是在浏览器每一帧的时间里,预留出来一部分给JS线程(从 源码 可以看到预留的时间是 5ms)。//react/packages/scheduler/src/forks/SchedulerHostConfig.default.js//Schedulerperiodicallyyieldsincasethereisotherworkonthemain//thread,likeuserevents.Bydefault,ityieldsmultipletimesperframe.//Itdoesnotattempttoalignwithframeboundaries,sincemosttasksdon't//needtobeframealigned;forthosethatdo,userequestAnimationFrame.letyieldInterval=5;如果预留的时间用完了,JS线程还没执行完,那么JS线程就会被中断阻塞,GUI渲染线程获得执行权,这一帧执行完了,React 则继续被中断的任务。其实,浏览器已经实现了这一个API,参见 requestIdleCallback。由于兼容性等原因,React 实现一套自己的Polyfill,这就是 Scheduler(调度器),一起组成了 React16 的新架构:Scheduler:调度器。Reconciler:协调器。由 StackReconciler 变成 FiberReconciler。Renderer:渲染器。React16 的Reconciler和Renderer也不再像 React15 一样交替工作,原因很简单,中断更新会带来一个问题——渲染不完全。所以 React16 的解决方法是给VDOM打标记,然后统一更新,具体流程如下:Scheduler发现浏览器有空闲时间,把更新任务交给Reconciler;Reconciler给需要变化的组件打上 增/删/更新 的Tag(ReactSideEffectTags);当所有组件都打上标记后,才会交给Renderer处理。费这么多时间重写架构就只是为了提升运行时性能吗?duck不必,其实 ConcurrentMode 才是架构重写的源动力,也是 React 未来的发展方向。在这个架构基础下,也会有更多的基于 ConcurrentMode 的上层应用产生。3.ConcurrentMode3.1模式介绍根据 官网 的介绍我们了解到:ConcurrentMode是什么?ConcurrentMode 是 React 的一组新功能。可帮助应用保持响应,并根据用户的设备性能和网速进行适当地调整。ConcurrentMode的特性?可以控制渲染流程,可中断JS执行,把控制权交还给浏览器。并发,引入优先级调度算法,可以并发执行多个更新任务。将人机交互的研究成果投入实际的应用当中。所谓的人机交互研究成果,举个例子,对于不同的UI交互,人们对于它的“忍受度“还是有比较大的差别,比如点击和页面跳转,可以忍受稍长时间的等待,但对于文本输入之类的交互,就需要比较比较快的响应。很明显,这两种交互在UI的渲染过程中应该有优先级,React 作为UI框架,期望通过 ConcurrentMode 将这种优先级的判断给完美地解决掉。3.2尝试demo尝试对比一下同步更新和异步更新,在快速输入时候的性能表现。同步更新异步更新
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 会员注册

本版积分规则

QQ|手机版|心飞设计-版权所有:微度网络信息技术服务中心 ( 鲁ICP备17032091号-12 )|网站地图

GMT+8, 2024-12-27 00:20 , Processed in 0.409873 second(s), 27 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表