文章所介绍内容基于chrome浏览器,当我们打开一个网页时,观察任务管理器,会发现有大于4个进程,浏览器进程,GPU进程,网络进程,标签页面进程,插件进程,为什么是这么多进程?
这篇文章主要站在浏览器进程架构模型的发展史来聊一下页面的渲染,及渲染过程中,进程之间是如何通信的。
这些进程的职责是什么,怎么来的呢?为什么这么设计呢?
要了解进程架构演进,需要先了解进程的几个特点:
06年及以前,早起的架构都是单进程架构
早期单进程架构是页面渲染和网络下载都是运行在同一个浏览器主进程中,而dom/com解析,js脚本执行,图像输出,插件运行都运行在同一个线程中,这样也带来了一系列的问题:
为了以上问题,第一版多进程架构模型出现
为了解决单进程问题,将渲染进程按照任务类型进行拆分,将主要影响浏览器进程稳定和安全的插件任务,渲染任务拆分出独立的进程,并且将剥离出来的插件进程、渲染进程封装在沙箱中,操作系统资源需要经过浏览器进程层操作。
开篇的任务管理器展示的图片,打开一个标签页有4个以上的进程,这是为什么呢?
随着浏览器承载的内容越来越丰富,对于展现的形式也越来越酷炫,很多动画效果、3D效果、及浏览器本身UI功能也越来也丰富,这导致浏览器主进程也承载着更多的任务,所以为了浏览器的稳定性考虑,进一步进行拆分
这个就解释了我们打开一个标签页面的时所用看到的进程数量为什么4个以上了,插件进程和渲染进程是多个的,而网络进程和GPU进程是独立的进程,由浏览器主进程管理维护,进程之间的通信和对操作系统资源的操作都由浏览器主进程管理,这样也就让浏览器主进程的职责划分的更加清晰
问题:
这有些关键字:更内聚、松耦合、易维护和扩展,简单、稳定、高速、安全、多设备,其他的可以自己思考一下了,这不就是一个小型的操作系统要做的事情么,目前很多微服务的、微前端架构的思想都是如此,面服务是目前主流的思想。
以上从浏览器进程模型演进介绍了打开一个页面所启动的进程数量,接下来我们从标签页来分析下进程数量。
为了演示我们简单用apache创建几个站点
<VirtualHost *:80>
DocumentRoot "D:/workspace/learn/test/other.com"
DirectoryIndex index.html
ServerName other.com
ServerAlias other.com
</VirtualHost>
<VirtualHost *:80>
DocumentRoot "D:/workspace/learn/test/test.com"
DirectoryIndex index.html
ServerName test.com
ServerAlias test.com
</VirtualHost>
<VirtualHost *:80>
DocumentRoot "D:/workspace/learn/test/local.test.com"
DirectoryIndex index.html
ServerName local.test.com
ServerAlias local.test.com
</VirtualHost>
<VirtualHost *:80>
DocumentRoot "D:/workspace/learn/test/beta.test.com"
DirectoryIndex index.html
ServerName beta.test.com
ServerAlias beta.test.com
</VirtualHost>
我们看下下面几种打开网站的方式
新标签页打开,浏览器会默认为其创建一个独立的渲染进程,每个站点不管是不是同一站点,均为其创建一个渲染进程
可以看到下图,每个标签页面,对应一个进程id
可以看到使用iframe方式打开的页面,同一站点共用了一个渲染进程,这是因为在一个标签页内使用iframe的方式打开页面,其子页面和父页面之间建立连接关系,并且是同一站点的则会默认共用一个渲染进程
如下图:
当在主页面test.com中已<a> 标签的方式在新标签中打开页面是,同一站点也共用一个渲染进程,那是因为使用a标签打开新页面的方式,也会为站点之间创建连接,使用同一浏览上文组
<body>
test.com <br>
<a target="_blank" href="http://test.com/index4.html">http://test.com/index4.html</a> <br>
<a target="_blank" href="http://local.test.com">http://local.test.com</a> <br>
<a target="_blank" href="http://beta.test.com">http://beta.test.com</a><br>
<a target="_blank" href="http://other.com">http://other.com</a><br>
</body>
通过上图可以得到如下结论:
我们再来进一步看一下,具有同一浏览上下文组的页面,如何在脚本中体现之间关系。还是上面的图
-- 切换到test.com页面(test.com页面是由test.com页面中a标签打开),在控制台查看window.opener
会发现同源站点,具有同一浏览上下文组,子页面可以使用window.opener.document操作父页面dom
-- 我们切换到local.test.com页面(local.test.com页面是由test.com页面中a标签打开),在控制台查看window.opener
会发现同站点,使用同一浏览上下文组,依然不能够使用window.opener.document操作父页面的dom,这是浏览器同源策略的限制,opener对象会查看到浏览上线文组js对象
-- 我们切换到other.com页面(other.com页面是由test.com页面中a标签打开),在控制台查看window.opener
会发现不同站点,具有同一浏览上下文组,子页面不可以使用window.opener.document操作父页面dom和js对象
-- 我们切换到local.test.com页面(local.test.com页面是在新标签页中打开),在控制台查看window.opener发现为null
会发现在不同进程中,不具有同一浏览上下文组的页面之间是相互隔离的
-- 如果我们在a标签中添加rel=noopener属性,那么和在新标签页单独打开站点是一样的,noopener这个属性是告诉与当前父业面不共用浏览上下文组
<body>
test.com <br>
<a target="_blank" rel="noopener" href="http://test.com/index4.html">http://test.com/index4.html</a> <br>
</body>
test.com/index5.html中使用a标签,rel="noopener"属性时,打开的页面进程使用情况如下
两个站点使用同一渲染进程的两个条件
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。