默认情况下,多进程浏览器的一个Tab下的确就一个渲染进程,不过相信各位也看到过多个Tab页面共用一个渲染进程的情况。事实上,也存在一个Tab下有多个渲染进程的情况,这其实与window.opener属性以及浏览器安全策略——站点隔离相关。(文章基于chrome 版本 90.0.4430.11测试)
怎么看浏览器的渲染进程?
在A页面(父页面)定义了一个打印参数值的方法test()
,设置一个在新窗口打开B页面的链接,一个window.open()
在新窗口打开B页面的链接,还注释了一个链接到百度首页的iframe。
<script>
function test(n) {
console.log(n)
}
</script>
<body>
<a href="B.html" target="_blank">to B page </a><br />
<a href="#" onclick="javascript:window.open('B.html')">window.open to B page </a>
<!-- <iframe src="https://www.baidu.com" height="400" width="600"></iframe> -->
在B页面(子页面)分别定义了一个调用父页面test
方法的方法,还定义了一个将父页面地址改变的方法,还有一个打开C页面的方法。
<body>
<button onclick="useOpenerMethod()">使用父页面的方法</button>
<button onclick="changeOpener()">盗换父页面</button>
</body>
<script>
function useOpenerMethod(){
window.opener.test(1234);
<span class="token punctuation">}</span>
<span class="token keyword">function</span> <span class="token function">changeOpener</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span>
window<span class="token punctuation">.</span>opener<span class="token punctuation">.</span>location<span class="token punctuation">.</span>href<span class="token operator">=</span><span class="token string">"https://www.baidu.com"</span>
<span class="token punctuation">}</span>
通过浏览器的任务管理器可以观察到每新建一个Tab页,都会新建一个渲染进程。
取消对A页面iframe那部分代码的注释,启动A页面,打开浏览器任务管理器可以看到有个叫做辅助框架的进程,打开正是我们iframe的设置的百度页面。也就是说一个Tab下是可以不止一个渲染进程的。
通过链接每打开一个B页面就会分配独立的CPU资源
A,B页面共用系统资源,也就是在同一个渲染进程下。即多个Tab可包含在同一个渲染进程
情景五:观察使用链接和window.open()打开的B页面方法的调用情况 |
链接打开的B页面:
window.open()
打开的B页面:
可见window.open()
打开的B页面能调用A页面的方法和改变A页面的网址。
关于window.opener
属性我就不做过多阐述了,各位可看下我这篇文章window对象的opener知多少
window.opener
属性是一个可读可写的属性,可返回对创建该窗口的 Window 对象的引用。
简单点说,就是从父页面打开一个子页面,子页面是可以读取和修改父页面的信息的(注意:有一定的限制条件)。
为什么情景一每次新建一个A页面就会多一个渲染进程呢? |
通过URL打开的各个页面都毫无关联的,并不会因为在同一个域名下就会将渲染进程合并为一个。
原因在于它们的window.opener
属性都为null
,说明都是独立开启,没有任何页面依赖关系,资源相互独立,自然就要给其分配独立的运行内存空间。
浏览器实现了站点隔离,跨域读取阻止。网站隔离有效地使不受信任的网站更难访问或窃取您在其他网站上的帐户中的信息。
站点隔离(site-isolation),所有跨站点的导航都将成为跨进程的,因此来自不同站点的文档不会彼此共享一个进程,然后将外部站点独立出一个渲染进程。这样就可以避免外部网站的数据进入父站点的渲染进程读取内存数据。一般对iframe才会独立一个辅助框架进程。
情景三通过链接每打开一个B页面就会分配独立的CPU资源 |
直接使用<a>
标签打开的新页面,得到的window.opener
属性的值都是null
。
情景四window.open()打开B页面与父页面共享渲染进程 |
通过window.open()
打开新页面时可以获取到window.opener
属性
情景五其实是对opener属性的补充和例证。
📌注意:谷歌浏览器的优化策略
还有一种情况就是,你不停的打开新的标签页,也会合并为一个渲染进程,但是当你在新标签页搜索或者查询之后,也会将该页面独立出来一个渲染进程。
- 父页面的打开的子页面在没有跨域访问的情况下,是会共用父页面的渲染进程的。(more tab one process)
- 页面中采用iframe框架引入其他页面,则iframe会独立成辅助框架,有自己的渲染进程。(one tab more process)
- 共用渲染进程的数个页面,当顶级的父页面关闭了或者跨域了,则会禅让该渲染进程。
- 新建的标签页也会合并为一个渲染进程,仅限不进行搜索查询的时候,这是谷歌刘浏览器的内存优化策略。