1.进程是具有一定独立功能的程序在一个数据集上的一次动态执行的过程,是操作系统进行资源分配的最小单位;线程是程序执行的最小单位,同一进程下的各个线程之间共享程序的内存空间。
2.前端常见进程
1)browser进程,是浏览器的主进程,该进程只有一个,负责浏览器界面的显示,与用户交互,比如前进后退等
2)第三方插件进程,每种类型的插件都对应一个进程,当使用该插件时,才创建进程
3)GPU进程,这个进程也只有一个,用于3D绘制等
4)渲染进程,每一个tab页面都有一个渲染进程,而且互相之间是不影响的,主要用来渲染页面,进行脚本执行等。在这个进程中,还有界面渲染线程,js引擎线程,http请求线程。浏览器事件触发线程等
3.前端常见线程
1)界面渲染线程:负责渲染浏览器界面,解析html,css,建立DOM树等,当我们修改了一些元素的颜色或者背景色,页面就会重绘,当我们修改元素的尺寸,页面就会回流,回流比重绘的成本要高。
2)Js引擎线程:负责解析js脚本,运行js代码,一个tab页面无论什么时候都只能有一个js线程在运行js程序,界面渲染线程与JS引擎线程是互斥的,浏览器渲染的时候遇到<script>标签,就会停止界面的渲染,然后js引擎线程开始工作,执行里面的js代码,等js执行完毕,js引擎线程停止工作,界面渲染经常继续渲染下面的内容。所以如果js执行时间太长就会造成页面卡顿的情况,浏览器之所以遇到script标签就先执行js代码,是因为js的内容可能会影响到dom树的结构,不至于发生页面混乱。
3)事件触发线程,用来控制事件循环,并且管理着一个事件队列。当js执行碰到事件绑定和一些异步操作(如AJAX异步请求等),会走事件触发线程,将对应的事件添加到对应的线程中,(比如定时器操作,便把定时器事件添加到定时器线程),等异步事件有了结果,再把他们的回调操作添加到事件队列,等待js引擎线程空闲时来处理。因为JS是单线程,所以这些待处理队列中的事件都得排队等待JS引擎处理
4)定时触发器线程,setInterval与setTimeout所在线程
5)异步http请求线程,当执行到一个http异步请求时,就把异步请求事件添加到异步请求线程,等收到响应,再把回调函数添加到事件队列,等待js引擎线程来执行
4.一个页面是一个进程、由这一页面产生的新页面同属此进程!
浏览器的多进程架构设计会让每一个页面会拥有一个自己独立的进程,按照这个逻辑来说单个页面的卡死或崩溃应该只会造成该页面所处的进程崩溃,而不会影响其他页面的进程(经观察,目前的谷歌浏览器、edge浏览器采用的是这种策略,甚至打开一个页面进程会增加两三个),但是有一种情况是多个页面使用同一进程,这就是”同一站点“。
Chrome 的默认策略是(我使用的谷歌并非如此,而搜狗浏览器具有这种特性)每个标签对应一个渲染进程。但是如果从一个页面打开了新页面,而新页面和当前页面属于同一个站点,那么新页面会复用父页面的渲染进程。官方把这个默认策略叫做”process-per-site-instance"。
简单的来说就是,如果几个页面属于同一站点,那么他们将会被分配到同一个渲染进程中。
所以这种情况下,一个页面崩溃了,会导致同一站点的页面同时崩溃,因为他们使用了同一个渲染进程。
那么为什么要让他们在同一个进程里面呢?
因为在一个渲染进程中,他们就会共享 JS 的执行环境,也就是说 A 页面可以直接在 B 页面中执行脚本。因为是同一家公司的站点,所以这个需求是存在的。
名词解释:同一站点
我们将”同一站点“定义为根域名(例如,http://baidu.com)加上协议(例如,https:// 或者 http:// ),还包含了该根域名下的所有子域名和不同的端口,比如下面这三个:
https://baidu.com
https://www.baidu.com
https://www.baidu.com:8080
以上三个页面都是属于同一站点,因为他们的协议都是 https ,而且根域名也都是 baidu.com 。