React Fiber 浅析

综述:“fiber” reconciler 是一个新尝试,致力于解决 stack reconciler 中固有的问题,同时解决一些历史遗留问题。Fiber 从 React 16 开始变成了默认的 reconciler。

1.背景:React 15 面临的一个问题

我们知道从广义上来讲,浏览器是单线程的,它将 GUI 描绘,时间器处理,事件处理,js 执行,远程资源加载统统放在一起。

在 React 15 及之前的版本,React 在对组件进行更新时,如果需要渲染更新的组件过于庞大,js 执行就会长时间占据主线程,导致页面的响应变慢。

当然 React 也提供了优化的手段(shouldComponentUpdate),但是这种优化方式更多是依赖于使用者自身,这种单纯的人肉优化并没有很好地改善这种情况。

2.前置概念

屏幕刷新率和 FPS

当前大多数的屏幕刷新率都是 60hz,也就是每秒屏幕刷新 60 次,低于 60hz 人眼就会感知卡顿掉帧等情况。

FPS (frame per second) 是界面每秒刷新的次数,理论上 FPS 越高人眼觉得界面越流畅。比较理想的情况是在两次屏幕硬件刷新之间,浏览器正好进行一次刷新,实际体验也会很流畅。

如果浏览器重绘一次的时间是硬件多次刷新的时间,那么人眼将感知卡顿掉帧等, 所以浏览器对一次重绘的渲染工作需要在 16ms (1000ms/60) 之内完成,也就是说每一次重绘小于 16ms才不会卡顿掉帧。

浏览器在一帧里完成的工作

React Fiber 浅析_第1张图片

3.React 源码简析

React 采用 monorepo 的管理方式。仓库中包含多个独立的包,以便于更改可以一起联调,并且问题只会出现在同一地方。

React Fiber 浅析_第2张图片

渲染器 (Renderers) 和协调器 (Reconcilers)

渲染器:用于管理一棵 React 树,使其根据底层平台进行不同的调用。

协调器:不同的渲染器彼此共享一些代码。我们称 React 的这一部分为“reconciler(协调器)”

Fiber 架构的目标

React Fiber 浅析_第3张图片

React Fiber 浅析_第4张图片

4.Fiber 架构的目标

1. 能够把可中断的任务切片处理

2. 能够调整优先级,重置并复用任务

3. 能够在父元素与子元素之间交错处理,以支持 React 中的布局

4. 能够在 render() 中返回多个元素

5. 更好地支持错误边界

运行时存在的实例:

react15之前:

DOM - 真实的 DOM 节点

Instances - react 维护的虚拟 DOM 节点

Elements - 对 UI 进行描述 eg. type, props

react16:

DOM - 真实的 DOM 节点 effect - 即副作用 (side effect),包括 DOM change 等操作

workInProgress - fiber tree 建立的当前进度快照,用于断点恢复

fiber - fiber tree 与 vDOM tree 类似,用来描述增量更新所需的上下文信息

Elements - 对 UI 进行描述 eg. type, props

总结一下:

Reconciliation 以 fiber tree 为蓝本,把每个 fiber 作为一个工作单元,自顶向下逐节点构造 workInProgress tree(构建中的新 fiber tree)。具体过程如下:

如果当前节点不需要更新,直接把子节点 clone 过来,跳到5;要更新的话打个 tag 更新当前节点状态(props, state, context等) 调用 shouldComponentUpdate(),false 的话,跳到5 调用 render() 获得新的子节点,并为子节点创建 fiber(创建过程会尽量复用现有 fiber,子节点增删也发生在这里) 如果没有产生 child fiber,该工作单元结束,把 effect list 归并到 return,并把当前节点的 sibling 作为下一个工作单元;否则把 child 作为下一个工作单元 如果没有剩余可用时间了,等到下一次主线程空闲时才开始下一个工作单元;否则,立即开始做 如果没有下一个工作单元了(回到了 workInProgress tree 的根节点),第 1 阶段结束,进入pendingCommit 状态

Fiber 架构其实就是 React 自己内部实现了一套调度系统,通过某些调度策略合理地分配 CPU 资源,达到快速响应用户,让用户觉得够快,不阻塞用户的交互的目标。

这一套调度系统还有一点好处:

给浏览器一点喘息的机会,他会对代码进行编译优化(JIT)及进行热代码优化,或者对 reflow 进行修正。

你可能感兴趣的:(前端框架,react,javascript)