引擎
JS引擎
组成
- parser:负责把 javascript 源码转成 AST
- interperter:解释器, 负责转换 AST 成字节码,并解释执行
- JIT compiler:对执行时的热点函数进行编译,把字节码转成机器码,之后可以直接执行机器码
- gc(garbage collector):垃圾回收器,清理堆内存中不再使用的对象
流水线:解析源码成AST,之后AST转换成字节码,解析之行字节码。运行时会收集函数执行的频率,对于到达阀值的热点代码回转换成机器吗(JIT),然后直接执行。(暂时只要知道就好了)
渲染引擎
1 将html用parser解析成dom
2 将css用parser解析成cssom
3 合并、计算布局样式,生成render tree,把内容复制到显存由显卡完成渲染
浏览器"帧"是什么
前端可关注五大关键渲染路径
graph LR
JS动画/Javascript --> 样式计算/Style --> 布局/Layout --> 绘制/Paint --> 合成/Composite
不是说渲染的过程只有这5个部分,而是最应该关注的是这五个步骤,因为这五个步骤我们拥有最大控制权。
三种更新视图的方式
这个图也很直观的表示出回流和重绘的关系:回流一定会重绘,重绘不一定会回流
"帧"
回流reflow、重绘repaint
回流:通过构造渲染树,我们将可见DOM节点以及它对应的样式结合起来,可是我们还需要计算它们在设备视口(viewport)内的确切位置和大小,这个计算的阶段就是回流
重绘:我们通过构造渲染树和回流阶段,我们知道了哪些节点是可见的,以及可见节点的样式和具体的几何信息(位置、大小),那么我们就可以将渲染树的每个节点都转换为屏幕上的实际像素,这个阶段就叫做重绘节点。
关系
JS引擎只会执行执行,渲染引擎只会不断布局渲染,而且两者互斥,那么如何结合一起 -> Event loop
Event loop是什么
宿主环境为了集合渲染渲染和JS引擎,也为了处理JS执行时的高优先级任务而设计。因此也能说明为何各环境的eventloop不尽相同
一次event loop
graph TD
宏任务 --> 微任务 --> check渲染 --> rAF切换渲染线程 --> check/worker --> requestidlecallback/离渲染还有时间或者timeout到了/
由于js执行和渲染回相互阻塞,如果JS处理时间如果太长,就会出现类似“丢帧”的情况,这个也是为什么需要fiber化的原因
- rAF不属于宏任务,也不属于微任务,而是每次loop结束发现需要渲染时,在渲染执行前都需要执行的回调函数
参考链接: