浏览器的进程
浏览器是多进程的,每打开一个tab页就会新增一个进程,如果我们使用Chrome打开很多标签页不关,电脑会越来越卡
浏览器包含哪些进程
Browser进程
- 浏览器的主进程,用于管理协调各个其他进程
- 负责浏览器的界面显示,与用户的交互以及页面的前进,后退等
- 网络资源的下载与管理
第三方插件进程
- 每种类型的插件对应一个进程,当使用该插件时才创建
GPU进程
- 该进程也只有一个,用于3D绘制等等
渲染进程
- 即通常所说的浏览器内核(Renderer进程,内部是多线程)
- 每个tab一个渲染进程,互不影响
- 主要作用是进行页面渲染,脚本执行,事件处理
重点:renderer进程
页面的渲染,js的执行,事件的循环,都在渲染进程内执行,所以我们要重点了解渲染进程
GUI渲染进程:重点
-
负责渲染浏览器的页面,解析HTML,CSS,构建DOM树和RenderObject树,布局和绘制等
- 解析HTML文件(发送过来的HTML文件先是01比特流,由计算机转换为字符串)再转为浏览器认识的节点,生成DOM树
- 解析CSS,生成CSSOM(css规则树)
- 把DOM树和CSSOM结合就得到了rendering树:渲染树的作用就是将DOM树与CSSOM的内容一一结合并且捕获可见内容
-
进行重绘(Repaint):当我们修改了元素的颜色或者背景色就会发生重绘。(重绘就是房子重新上色)
-
进行回流(Reflow):当我们修改了元素的尺寸就会发生回流。(回流是房子拆了重建)
浏览器对回流和重绘的优化:浏览器会维护一个重绘回流的队列,当触发一定的阈值就会清空队列进行批处理
但是调用以下方法浏览器会立刻清空队列,执行回流和重绘:offsetLeft, offsetTop, offsetWidth, offsetHeight等
-
回流的成本比重绘高,我们要避免回流和重绘
1.避免频繁操作样式:通过增改类名一次性改变style 2.避免频繁操作DOM:脱离文档流、使用文档碎片(document fragment)、隐藏后修改完再显示 3.避免多次访问上面的属性与方法 4.复杂动画:使用绝对定位脱离文档流 5.触发CSS3硬件加速:使用transfrom,opactity,filters,Will-change
-
GUI线程与js引擎线程是互斥的
- js引擎线程在执行的时候GUI线程被挂起
- GUI更新会保存在一个队列中等待js引擎线程空闲时立即执行
js引擎线程
-
js引擎线程就是js内存,用于处理JavaScript脚本(例如V8引擎)
-
js引擎一直等待任务队列中任务的到来,然后加以处理
为什么说js的单线程的?
1.浏览器同时只能有一个js引擎在执行js任务
2.一个renderer进程无论何时只有一个js引擎线程
-
GUI渲染线程与js引擎线程是互斥的,js引擎线程会阻塞GUI渲染线程
- 就是我们常遇到的js执行时间过长,造成页面的渲染不连贯,导致页面渲染加载阻塞(就是加载慢)
- 例如浏览器渲染的时候遇到
<script>标签,就会停止GUI的渲染,然后js引擎线程开始工作,执行里面的js代码,等js执行完毕,js引擎线程停止工作,GUI继续渲染下面的内容。所以如果js执行时间太长就会造成页面卡顿的情况
怎么样解决上述问题呢?
可以把script标签放在最后,也有使用async和defer属性,async:异步加载script,加载完毕立即执行,执行时阻塞渲染,执行顺序可能改变;defer:异步加载script,加载完成等待渲染完成再执行,一定按照原本的顺序执行
事件触发线程
- 属于浏览器而不是js引擎线程,用来控制事件循环和管理事件队列(Task queue)
- 当js执行遇到事件监听和异步函数(如绑定鼠标点击事件,setTimeout,Ajax异步请求等),会通过事件触发线程将事件添加到对应的线程中,等异步任务有结果,便把他们的回调函数添加到事件队列中,等待js引擎线程空闲时处理
- 当对应事件符合触发条件时,该线程将此事件添加到待处理队列末尾,等待js引擎空闲时处理
- 因为js是单线程,所以这些待处理队列中的事件都得排队等待js引擎处理
定时触发线程
1.专门用于监控setInterval与setTimeout的线程
2.浏览器的定时器不是js引擎计时的
3.当定时器到时,定时触发线程就会把此定时器的回调函数交给事件触发进程,由事件触发进程将这个定时器的回调放到task queue(宏任务队列)中等待js空闲时执行
异步http请求线程
1.每次新建XMLHttpRequest就新建一个异步http请求线程
2.当这个异步请求状态变化就把响应的回调交给事件触发进程,由事件触发进程将这个异步请求的回调放到task queue(微任务队列)中等待js空闲时执行
为什么要这样控制事件触发?
为了让浏览器上的所有线程的工作都很单一且独立,符合单一原则
定时触发线程只管理定时器且只关注定时不关心结果,定时结束就把回调扔给事件触发线程
异步http请求线程只管理http请求同样不关心结果,请求结束把回调扔给事件触发线程
事件触发线程只关心异步回调入事件队列