1123 字
6 分钟
浏览器的渲染进程(renderer)
简述渲染进程Renderer
页面的渲染,JS的执行,事件的循环,都在渲染进程内执行。
渲染进程Renderer的主要线程
GUI渲染线程
- 负责渲染浏览器界面,解析HTML,CSS,构建DOM树和RenderObject树,布局和绘制等
- 解析html代码(HTML代码本质是字符串)转化为浏览器认识的节点,生成DOM树,也就是DOM Tree
- 解析css,生成CSSOM(CSS规则树)
- 把DOM Tree 和CSSOM结合,生成Rendering Tree(渲染树)
- 当我们修改了一些元素的颜色或者背景色,页面就会重绘(Repaint)
- 当我们修改元素的尺寸,页面就会回流(Reflow)
- 当页面需要Repaing和Reflow时GUI线程执行,绘制页面
- **回流(Reflow)比重绘(Repaint)**的成本要高,我们要尽量避免Reflow和Repaint
- GUI渲染线程与JS引擎线程是互斥的
- 当JS引擎执行时GUI线程会被挂起(相当于被冻结了)
- GUI更新会被保存在一个队列中等到JS引擎空闲时立即被执行
JS引擎线程(主线程)
- JS引擎线程就是JS内核,负责处理Javascript脚本程序(例如V8引擎)
- JS引擎线程负责解析Javascript脚本,运行代码
- JS引擎一直等待着任务队列中任务的到来,然后加以处理
- 浏览器同时只能有一个JS引擎线程在运行JS程序,所以js是单线程运行的
- 一个Tab页(renderer进程)中无论什么时候都只有一个JS线程在运行JS程序
- GUI渲染线程与JS引擎线程是互斥的,js引擎线程会阻塞GUI渲染线程
- 就是我们常遇到的JS执行时间过长,造成页面的渲染不连贯,导致页面渲染加载阻塞(就是加载慢)
- 例如浏览器渲染的时候遇到script标签,就会停止GUI的渲染,然后js引擎线程开始工作,执行里面的js代码,等js执行完毕,js引擎线程停止工作,GUI继续渲染下面的内容。所以如果js执行时间太长就会造成页面卡顿的情况
事件触发线程
- 属于浏览器而不是JS引擎,用来控制事件循环,并且管理着一个事件队列(task queue)
- 当js执行碰到事件绑定和一些异步操作(如setTimeOut,也可来自浏览器内核的其他线程,如鼠标点击、AJAX异步请求等),会走事件触发线程将对应的事件添加到对应的线程中(比如定时器操作,便把定时器事件添加到定时器线程),等异步事件有了结果,便把他们的回调操作添加到事件队列,等待js引擎线程空闲时来处理。
- 当对应的事件符合触发条件被触发时,该线程会把事件添加到待处理队列的队尾,等待JS引擎的处理
- 因为JS是单线程,所以这些待处理队列中的事件都得排队等待JS引擎处理
定时触发器线程
setInterval与setTimeout所在线程- 浏览器定时计数器并不是由JavaScript引擎计数的(因为JavaScript引擎是单线程的,如果处于阻塞线程状态就会影响记计时的准确)
- 通过单独线程来计时并触发定时(计时完毕后,添加到事件触发线程的事件队列中,等待JS引擎空闲后执行),这个线程就是定时触发器线程,也叫定时器线程
- W3C在HTML标准中规定,规定要求
setTimeout中低于4ms的时间间隔算为4ms
异步http请求线程
- 在XMLHttpRequest在连接后是通过浏览器新开一个线程请求
- 将检测到状态变更时,如果设置有回调函数,异步线程就产生状态变更事件,将这个回调再放入事件队列中再由JavaScript引擎执行
- 简单说就是当执行到一个http异步请求时,就把异步请求事件添加到异步请求线程,等收到响应(准确来说应该是http状态变化),再把回调函数添加到事件队列,等待js引擎线程来执行
EventLoop轮询处理线程 (重中之重)
这里单独拿出一篇文章将这个
浏览器的渲染进程(renderer)
https://nollieleo.github.io/posts/浏览器的渲染进程renderer/