从一个标签页中打开另一个标签页,如果这两个标签页属于同一站点(相同协议,相同根域名),则他们会共用一个渲染进程。

如果分别打开两个相同站点的标签页,则使用不同的渲染进程。
同一站点的渲染进程.png

为什么分别打开的两个相同站点在不同的渲染进程?

这与标签之间的连接方式有关。

标签之间的连接

  • 通过 a 标签来和新标签建立连接。
  1. <a href="https://time.geekbang.org/" target="_black" class=""> geek time </a>

这种方式会使新标签中的 window.opener 指向老标签页中的 window。这样在新 tab 页中就可以通过 opener 操作老 tab。即这两个 tab 存在连接。

  • 通过 window.open 在 A 中打开 B
    这样也是有连接的。

上述两种方式,即使不属于同一站点,也能通过 opener 建立连接。在 whatWG 规范中,把这种有相互连接关系的标签页称为浏览上下文组。一个 tab 中所包含的内容(window 对象、历史记录、滚动条位置等信息)称为浏览上下文。

Chrome 会讲浏览上下文组中属于同一站点的标签分配到同一个渲染进程中。这是因为如果一组标签页,既在同一个浏览上下文组中,又属于同一站点,那么它们可能需要在对方的标签页中执行脚本。因此,它们必须运行在同一渲染进程中。

结论:
分别打开的两个同一站点的 tab,由于它们之间没有连接关系,故不在同一个渲染进程。

例外

如果 a 连接的 rel 属性值使用了 noopener 和 noreferrer,则不会产生连接。
noopener 告诉浏览器通过这个链接打开的 tab 中的 opener 为 null。
noreferrer 告诉浏览器新打开的标签页不要有引用关系。

  • 示例

D272444A-ABA0-42FC-8317-10C674051F82.jpeg
0918F873-76DA-494F-845E-FDE9B12AE0D7.jpeg

站点隔离

Chrome 中实现了站点隔离的功能,意味着在标签页中的 iframe 也会遵守同一站点的分配原则。若有 tab 中的 iframe 与 tab 是同一站点且有连接关系,那么则运行在同一渲染进程。否则 iframe 运行在单独的渲染进程。

  • 例子
  1. <head>
  2. <title> 站点隔离:demo</title>
  3. <style>
  4. iframe {
  5. width: 800px;
  6. height: 300px;
  7. }
  8. </style>
  9. </head>
  10. <body>
  11. <div><iframe src="iframe.html"></iframe></div>
  12. <div><iframe src="https://www.infoq.cn/"></iframe></div>
  13. <div><iframe src="https://time.geekbang.org/"></iframe></div>
  14. <div><iframe src="https://www.geekbang.org/"></iframe></div>
  15. </body>
  16. </html>

在 Chrome 中的任务管理器里可以看到效果。

  • iframe 中渲染进程个数的计算

D283A5CB-340A-4929-BED4-2C2DD791B0A2.jpeg

同源策略对同一站点的限制

如果 A、B tab 属于同一站点,却不属于同源站点,AB 会处于同一渲染进程,但无法通过 opener 操作父标签页中的 DOM。

同一站点:根域名相同。(www.geek.com,time.geek.com)

思考题

  1. Chrome 为什么使用同一站点划分渲染进程,而不是使用同源策略来划分?

同一站点安全性有保障,资源复用方便,节约进程。

  1. 阿里云为什么要把 tab 做成无连接?

防止一个 tab 沦陷,导致其他 tab 全部沦陷。