# 浏览器进程
Browser进程:只有一个
- 负责浏览器界面显示、用户交互。例如:前进、后退
- 负责各个页面的管理,创建和销毁其他进程
- 网络资源管理。例如下载
GPU进程:一个
- 用于3D绘制等
浏览器渲染进程(Renderer进程)
- 内部是多线程的,即每个tab页所拥有的进程
- 负责页面渲染、脚本执行、事件处理等
第三方插件进程:每种类型的插件对应一个进程
# 浏览器渲染进程(浏览器内核)
图形用户界面GUI渲染线程
- 负责浏览器界面,包括解析HTML、CSS、构建DOM树、Render树、布局和绘制等
- 重绘或回流时由该线程负责
JS引擎线程
- 负责处理执行js脚本
- 等待任务队列的任务到来并执行
- 任务队列分为宏任务和微任务,其中微任务队列只有一个
- 浏览器只有一个js引擎
事件触发线程
- 归属于浏览器
- 回调函数(setTimeout、鼠标点击、ajax异步请求指定的函数)添加到事件线程中
- 当事件符合触发条件时,该线程把事件添加到任务队列队尾,等待js引擎处理
定时触发器线程
- setInterval与setTimeout所在进程
- 定时计时器并不是由js引擎计时的,因为js引擎是单线程的,当引擎处于堵塞状态,会影响计时的准确
- 计时完成被触发,事件会添加到任务队列队尾
- W3C规定,setTimeout中低于4ms的时间间隔算为4ms
异步HTTP请求线程
- 在XMLHttpRequest在连接后新启动的一个线程
- 线程检测到请求的状态变更后,会将回调函数添加到任务队列
# 为什么JS引擎是单线程
# 浏览器内核中线程之间的关系
# GUI渲染线程与JS引擎线程互斥
JS引擎可以修改DOM树,如果GUI线程在同时渲染页面,就会导致渲染线程获取的DOM元素信息和JS引擎操作DOM后的不一致。为了防止这种现象,GUI线程和JS引擎线程设计为互斥关系,当JS引擎执行时,GUI的渲染会被保存在一个队列中,等待JS引擎空闲时才进行渲染。因此要避免CPU密集型的计算,否则JS引擎阻塞,会导致渲染进程不能执行渲染。例如:
while(1)
alert(1)
会看到alert弹窗不会出现,就是因为js引擎陷入死循环,渲染引擎无法渲染。
# WebWorker
Web Workers 使得一个Web应用程序可以在与主执行线程分离的后台线程中运行一个脚本操作。这样做的好处是可以在一个单独的线程中执行费时的处理任务,从而允许主(通常是UI)线程运行而不被阻塞/放慢。
- WebWorker可以向浏览器申请一个子线程,该子线程服务于主线程,受主线程控制
- JS引擎线程与worker线程通过postMessage API进行通信
SharedWorker和WebWorker类似,区别在于SharedWorker被所有Renderer进程所共享,只有一个SharedWorker进程。
# 浏览器的渲染流程
浏览器输入url,浏览器主进程接管,开启一个下载线程
DNS查询,3次握手,建立连接,开始下载响应报文
将下载完的内容转交给Renderer进程
解析html,生成DOM树
解析CSS规则,生成CSSOM树
根据DOM树和CSSOM树生成Render树
根据Render树进行layout,负责元素节点的尺寸、位置计算
绘制Render树,绘制页面像素信息
浏览器将各层的信息发给GPU,GPU将各层合成,显示在屏幕
DOMContentLoaded事件触发时,仅当DOM加载完成,不包括样式表和图片
onLoad事件触发时,页面上所有DOM、样式表、脚本和图片都已经加载完成
参考:https://segmentfault.com/a/1190000013083967 (opens new window)
← 服务端渲染 渐进式Web应用PWA →