问题
最近在排查打开多个网页时,文件预览卡顿的问题,意外地发现了一个window.open的问题
- 文件预览流程是这样的,点击文件然后会跳转到新窗口打开
- 在工业上,一般会打开很多的文件,文件体积又大(经常性的几十兆,上百兆)
- 当打开很多图纸之后,会隐约感觉到页面有点点卡顿
- 打开十几个tag,卡顿也能理解,但是奇怪的是当关闭掉这些打开的零件之后,卡顿还是没有好转
- ....
一顿疯狂排查之后,发现竟然是浏览器内存没有被释放的原因:
可以看到,左边有一个蓝色的竖线,表示这几个页面是关联起来的
因为下面几个页面是用window.open的方式打开的,虽然是打开了新的tag页面,但是它们其实是和父级tag页面是共用一个进程
所以即使关闭了这些新打开的tag,只要父级tag不关闭,内存其实不会被释放掉的;
而且经常性地不会关闭主tag页面,这就导致了内存迟迟没有被释放,页面也就变得卡顿了
原因
默认情况下chrome会为每一个tab创建一个渲染进程,比如:
- 当我们在
url上输入一个新的url时 - 通过
a标签打开新页面时
都会创建一个新的进程,分配独立运行的内存空间
但是,通过window.open()的方式打开新页面,如果打开新页面的站点与当前页面的站点属于 “同一站点” ,会被分配到同一个渲染进程,这就导致多个tag页面共享一个进程
同一站点:协议 + 根域名 相同
在
window对象中有一个opener属性,指向的是创建该窗口的window对象的引用
当使用
window.open打开新页面的时候,window.opener指向的是当前的tag页面(父级tag)
所以这种方式跳转的页面,可以通过
opener属性访问父级页面的全局方法和数据
使用
a标签或者输入url的方式打开新页面,window.opener指向为null,说明是独立开启的,没有任何页面依赖,那么就会新建渲染进程,分配内存空间
解决
问题找到了,就好解决了,把window.open替换掉
用a标签代替是个不错的主意:
export const openwindow = (url: string) => {
const link = document.createElement('a')
link.href = url
link.target = '_blank'
document.body.appendChild( link)
link.click()
document.body.removeChild(link)
}