写点什么

React 的理念与 V16 的架构变化

作者:郭明
  • 2022 年 8 月 04 日
  • 本文字数:1499 字

    阅读完需:约 5 分钟

一、React 的理念

React 的核心理念是快速响应,具体来说,要应对两类场景:

1、CPU 瓶颈

JS 操作 DOM,到 GUI 渲染是串行的,在一个周期内完成。如果刷新率是 60Hz,刚需要在 16.6ms 完成 JS 脚本执行、样式布局、样式绘制工作。

当 JS 执行时间过长,会卡住样式布局和绘制,出现页面掉帧、卡顿的情况。比如,向视图渲染 3000 个 li,或执行一段重 CPU 计算。

当项目变得庞大、组件数量繁多时,也容易遇到 CPU 瓶颈。

以上原因,15 到 16 架构发生变化,采用时间切片,把大任务拆小,可在中断后恢复执行。

2、IO 瓶颈

发送网络请求后,由于需要等待数据返回才能进一步操作导致不能快速响应。

网络延迟客观存在,我们只能减少用户对网络延迟的感知。

为此,React 实现了 Suspense 功能及 useDeferredValue 这个 hook。

二、React15 的架构特点

1、Reconciler(协调器)

负责找出变化的组件,一般有如下过程:

(1)mount 的组件会调用 mountComponent,update 的组件会调用 updateComponent,这两个方法都会递归更新子组件。

(2)调用函数组件、或 class 组件的 render 方法,将 JSX 转化为虚拟 DOM

(3)将虚拟 DOM 和上次更新时的虚拟 DOM 对比

(4)通过对比找出本次更新中变化的虚拟 DOM

(5)交给 Renderer 将变化的虚拟 DOM 渲染到页面上

2、Renderer(渲染器)

负责将变化的组件渲染出来,可以通过不同的渲染器渲染到不同平台

(1)ReactDOM 渲染器,渲染到网页 DOM 上,以 HTML 的形成呈现

(2)ReactNative 渲染器,通过 RN 内核中转,渲染到原生(安卓、IOS、Windows)界面

(3)ReactTest 渲染器,渲染到纯 JS 对象用于测试

(4)ReactART 染器,渲染到 Canvas 或 SVG

3、Reconciler 和 Renderer 交替工作,同步递归更新

从首次挂载或变更的组件开始,向所有子组件传递更新,递归下去,Reconciler 和 Renderer 交替工作,在同步状态下完成。

即从顶向下,一口气完成,不中断。

如果层级很深、变更的组件非常多,递归时间会超过 16ms,用户的交互就会卡顿。

三、React16 的进化

基于 15 的同步递归更新特点,随着应用越来越复杂,势必会影响快速响应的达成。

需要从底层调整架构,改造成异步可中断更新,在浏览器每一帧的时间(比如 16ms)中,预留一些时间给 JS 线程(预留的初始时间是 5ms,会根据刷新率来计算)。当预留的时间不够用时,React 将线程控制权交还给浏览器,使其有时间渲染 UI,React 则等待下一帧时间到来,然后继续被中断的工作。

这种将长任务分拆到每一帧中,像蚂蚁搬家一样一次执行一小段任务的操作,被称为时间切片(time slice)。可以通过使用 ReactDOM.unstable_createRoot 开启 Concurrent Mode。

四、React16 的架构特点

(1)Scheduler(调度器)

新增调度器,调度任务的优先级,高优任务优先进入 Reconciler。

内部模拟实现了一个 requestIdleCallback,解决这个原生 API 浏览器兼容性和触发频率不稳定的问题,实现更完备的优先级管理。

(2)Reconciler(协调器)

和 15 一样,负责找到变化的组件,但区别是,这个过程可中断,中断回来还能接着上次的位置继续找。

这是由内部实现的 Fiber 架构来支撑的。同时,Reconciler 与 Renderer 不再是交替工作。当 Scheduler 将任务交给 Reconciler 后,Reconciler 会为变化的虚拟 DOM 打上代表增/删/更新的标记。整个 Scheduler 与 Reconciler 的工作都在内存中进行。只有当所有组件都完成 Reconciler 的工作,才会统一交给 Renderer。

(3)Renderer(渲染器)

Renderer 根据 Reconciler 为虚拟 DOM 打的标记,同步执行对应的 DOM 操作,将变化的组件渲染到页面上。

五、小结

为了做到快速响应,CPU 的瓶颈通过并发特性的优先级中断机制解决,IO 的瓶颈则交给 Suspense 解决。


提 2 个问题:

1、Renderer 是不会被打断的吗?是否有大量更新超过 16ms 的情况呢?

2、哪些任务是高优先级的?高优先级任务是如何插入并先执行的?

发布于: 刚刚阅读数: 4
用户头像

郭明

关注

还未添加个人签名 2019.12.23 加入

一个搬书工,公众号“郭明说”

评论

发布
暂无评论
React的理念与V16的架构变化_React_郭明_InfoQ写作社区