谷歌浏览器新开页面进程问题

  开发项目过程中,会遇到点击页面上某个东西,要在新窗口中打开一个页面的需求。如果你认为是简简单单的打开一个新窗口,那就会掉进谷歌浏览器的坑里了。

  场景:A页面,点击按钮,新开窗口跳转到该项目的B页面,如果B页面的请求尚未结束,直接关闭B页面,此时A页面会卡死

  原因:谷歌浏览器在给新开窗口分配进程时,看是否同源,非同源页面会单独分配一个新进程,而同源页面只会分配一个相同的新进程。在上述场景中,A,B页面同源,所以谷歌浏览器只会分配一个进程,这就导致B页面在请求未结束时就关闭,A页面会卡死。

  下面来看一下不同方式打开新页面的浏览器分配进程情况。

一、查看谷歌浏览器的进程

  1、找到浏览器的自定义及控制图标

     2、点击找到更多工具

  3、点击更多工具并点击任务管理器

  4、进程如下:

二、使用a标签打开新窗口

  1、使用a标签打开非同源窗口

<a href="https://www.baidu.com/" target="_blank">新开窗口跳转到百度</a>
<a href="https://www.cnblogs.com/" target="_blank">新开窗口跳转到博客园</a>

  使用a标签分别打开了百度以及博客园首页,这两个非同源,所以浏览器会分配两个新进程。如下图:

  2、使用a标签打开同源窗口

<a href="https://juejin.im/" target="_blank">新开窗口掘金</a>
<a href="https://juejin.im/" target="_blank">新开窗口掘金</a>

  使用a标签打开掘金首页,这两个同源,所以浏览器只会分配一个新进程。如下图:

 三、使用window.open打开新窗口

  使用window.open打开新窗口与a标签打开结果相同

 <Button onClick={() => window.open('https://www.csdn.net/')}>window.open跳转到CSDN</Button>
 <Button onClick={() => window.open('https://www.csdn.net/')}>window.open跳转到CSDN(同源)</Button>
 <Button onClick={() => window.open('https://www.jianshu.com/')}>window.open跳转到简书(非同源)</Button>

  点击3个Button,打开3个新窗口,只分配了2个进程CSND同源,共用一个进程,简书单独一个进程

 四、如何解决同源同一进程

  一般来说,新开窗口肯定是想新开一个进程,这样两边页面不会受到影响。要想同源不同进程,就需要将新创建的标签页的 opener 属性设置为 null,表示在单独的进程中运行新标签页,这样浏览器就会给每一个新开窗口分配一个进程

  1、window.open设置opener为null不会起作用

const handleClick = () => {
    let otherWindow: any = window.open();
    otherWindow.opener = null;
    otherWindow.location = 'https://www.baidu.com/';
}
<Button onClick={handleClick}>window.open设置opener跳转到百度</Button>
<Button onClick={handleClick}>window.open设置opener跳转到百度</Button>

   将opener设置为null之后,再打开新窗口。结果浏览器并没有单独分配进程,还是同源分配一个进程。

  

  这就要使用a标签代替window.open来解决

   2、a标签添加rel="noopener noreferrer"解决同源同进程

<a href="https://www.baidu.com/" target="_blank" rel="noopener noreferrer">新开窗口添加rel跳转到百度</a>
<a href="https://www.baidu.com/" target="_blank" rel="noopener noreferrer">新开窗口添加rel跳
转到百度</a>

  a标签添加rel="noopener noreferrer"就相当于将新窗口的opener置为null,此时浏览器会给新开窗口都单独分配一个进程

五、项目中使用

  创建a标签并触发方法打开新页面

 let a = document.createElement('a');          //创建a标签
 a.setAttribute('href', url);               //url即为需要打开的新页面的url
 a.setAttribute('target', '_blank');           //_blank新窗口打开
 a.setAttribute('rel', 'noopener noreferrer');  //添加rel
 document.body.appendChild(a);    
 a.click();                         //触发click

   这样每次打开一个新窗口时,就会创建一个新的进程。

posted @ 2020-05-29 14:17  MinorF_γ  阅读(2132)  评论(0编辑  收藏  举报