前言
对 React 的定位
我们认为,React 是用 JavaScript 构建快速响应的大型 Web 应用程序的首选方式。它在 Facebook 和 Instagram 上表现优秀。
React 的 Stack Reconciler 也在渐渐在体验方面显示疲态
在 16.x 版本中将其最为核心的 Diff 算法整个重写
使其以“Fiber Reconciler”的全新面貌示人
问题
- Stack Reconciler 到底有怎样根深蒂固的局限性?
- Fiber 架构又是何方神圣?
前置知识
单线程的 JavaScript 与多线程的浏览器
多线程的浏览器除了要处理 JavaScript 线程以外
还需要处理各种各样的任务线程
其中也包括负责处理 DOM 的 UI 渲染线程
而 JavaScript 线程是可以操作 DOM 的。
导致了一个问题就是:如果渲染线程的 JavaScript 线程同时在工作,那么渲染结果必然是难以预测的
JavaScript 线程和渲染线程必须是互斥的;
当其中一个线程执行时,另一个线程只能挂起等待
当事件被触发时,对应的任务不会立刻被执行
而是由事件线程把它添加到任务队列的末尾
等待 JavaScript 的同步代码执行完毕后
在空闲的时间里执行出队
渲染层面的更新长时间地等待,界面长时间不更新,带给用户的体验就是所谓的“卡顿”
事件线程也在等待 JavaScript,这就导致你触发的事件也将是难以被响应的
为什么会产生“卡顿”这样的困局?
JavaScript 对主线程的超时占用问题
Stack Reconciler 是一个同步的递归过程
这个过程的致命性在于它是同步的,不可以被打断
Stack Reconciler 需要的调和时间会很长
这就意味着 JavaScript 线程将长时间地霸占主线程
进而导致我们上文中所描述的
渲染卡顿/卡死,交互长时间无响应等问题
设计思想:Fiber 是如何解决问题的
什么是 Fiber?
Filber 就是比线程还要纤细的一个过程
也就是所谓的“纤程”
纤程的出现意在对渲染过程实现更加精细的控制
- 从架构角度来看,Fiber 是对 React 核心算法的重写
- 从编码角度来看,Fiber 是 React 内部所定义的一种数据结构
- 从工作流的角度来看,Fiber 节点保存了组件需要更新的状态和副作用
Fiber 架构的应用目的是实现“增量渲染”
实现增量渲染的目的,是为了实现任务的可中断、可恢复,并给不同的任务赋予不同的优先级,最终达成更加顺滑的用户体验
render 的工作单元有着不同的优先级
React 可以根据优先的高度
去实现工作单元的打断和恢复
- componentWillMount
- componentWillUpdate
- shouldComponentUpdate
- componentWillReceiveProps
总结
React 16 中 Fiber 架构的架构分层和宏观视角下的工作流
关于 Fiber Reconciler 还有太多的谜题需要我们一一探索
- React 16 在所有情况下都是异步渲染的吗?
- Fiber 架构中的“可中断” “可恢复”到底是如何实现的?
- Fiber 树和传统虚拟 DOM 树有何不同?
- 优先级调度又是如何实现的?
- 。。。