为什么现代浏览器一个进程崩溃有时只会影响当前页面,而不会影响整个浏览器?

692 阅读4分钟

现代浏览器主要有四个进程:浏览器主进程、网络进程、渲染进程、GPU进程,如果有开启插件则会有插件进程。其中主进程、网络进程、GPU进程数量为1,渲染进程、插件进程为多个。

插件进程是打开一种插件,就会开启一个插件进程。

但是,浏览器开启多个页面时,渲染进程为一个或多个。默认情况下,浏览器只会为每个页面开启1个渲染进程。

首先了解一下什么叫同站点,同站点指的是多个站点的协议和根域名相同,也就是说只要多个域名的根域名和站点相同,就属于同一站点,即使二级域名不相同,也属于同一站点。

1、每个页面开启1个渲染进程的情况

  • 重新打开一个标签页时也会创建一个新的渲染进程,如上图,同为极客时间的标签,但是使用两个进程ID:2032,2088,因为2088进程所属页面是重新打开一个标签产生的。
  • 当从页面A打开页面B时,如果A、B两个页面不属于同站点,浏览器就会为每一个页面创建一个渲染进程。

此时,当A页面的渲染进程崩溃时,只会影响A页面,不会影响B页面。

2、多个页面共用一个渲染进程的情况

当从页面A打开页面B,如果A、B属于同站点,B页面就会复用A页面的渲染进程,因此该进程崩溃,就会造成A、B页面的崩溃。

例如这几个页面为一个进程ID,复用渲染进程。

3、测试结果

重点!!!

按照上面的这个说法,只要是同一站点,并且B页面是从A页面中打开的,那么A、B页面的渲染进程就会复用,为此我测试了几个网站,进行对比:

网站1:

打开time.geekbang.org/ (极客时间),并打开我的课程,查看进程:

发现极客时间的子页面和父页面的渲染进程确实是复用的,在子页面控制态使用window.opener查看父页面的信息,也是能查到的。

网站2:

打开x.threatbook.cn/(微步在线威胁情报社区…

发现渲染进程并没有复用!!

在打开的子页面的控制台查看父页面的信息,发现为null。

网站3:

打开juejin.cn/(掘金),并打开一个连…

发现渲染进程也没有复用,window.opener也为null。

所以,渲染复不复用还和winodw.opener有关!!

window.opener是什么呢?它是父页面的Window对象的引用,所以当window.opener为null时,也就意味着没有父页面,或者父子页面断绝关系了。那么什么情况下会使得父子页面断绝关系,导致渲染进程不能被复用?

常用的父页面打开子页面的方法有:a链接、window.open()。

建立关系的首要条件是父子页面属于同站点。

  • a链接默认没有指定当前页面与被打开页面之间的关系,所以默认打开的父子页面是断绝关系的,只有当设置rel='opener'时,父子页面才会建立关系,渲染进程才能复用,此时查看winow.opener是有值的。
  • 使用window.open打开新页面时,父子页面也会建立联系,复用渲染进程。

上面是同站点的父子页面的情况,那么非站点的呢?当父子页面不是同站点,也就是说存在跨域时,父子页面的联系就会丢失,所以才会造成渲染进程不能复用。

4、渲染进程不复用好还是不好呢?

渲染进程复用分析:

好处:

节省资源,因为多一个进程,就要多一分备用数据。

坏处:

一个页面崩溃,会影响另一个页面,因为渲染进程崩了。

5、总结

渲染进程的是否复用和window.opener是否有值有关,父子页面同站点且window.opener时,渲染进程复用,同站点和window.opener值存在是并的关系,二者有一个不成立,都会造成渲染进程的不复用。