在我上篇文章里,我提到一种使用iframe完成无阻塞脚本加载的方式,由于我对iframe的偏见很大,因此上篇文章里我没有展开讨论这个问题。javascript
文章发表后有位网友问了我这样一个问题,下面是他问题的原文,以下所示:css
我一个电商后台系统,用的表格控件是flexigrid,,里面是个iframe来的,每个tab就是一个iframe,如今遇到的问题就是,若是其中一个或者多个iframe在加载数据,还没加载完,若是这个时候,我再去开一个tab,也是查找数据,可能数据量很大,或者提交数据(其余的iframe可能还在加载数据),这个时候很容易出现浏览器卡死,一直转圈的现象,这个跟你说的这个js阻塞也有关系吧。跟这个js单线程的特性,线程阻塞有多大的关系~~
这个现象颇有趣,就和我在上篇文章里谈到我思考无阻塞脚本加载的源起同样,研究这个朋友提供的现象应该也能给咱们很大的收获。html
首先,这位朋友提到“若是其中一个或者多个iframe在加载数据,还没加载完,若是这个时候,我再去开一个tab,也是查找数据,可能数据量很大,或者提交数据(其余的iframe可能还在加载数据),这个时候很容易出现浏览器卡死,一直转圈的现象”,这个现象让我有个疑问:前端
首先咱们要明确页面使用iframe时候等于一个页面里嵌套一个页面,iframe的src指向的页面其实和父页面是相对独立的,那么一个带了iframe的页面,父页面的加载过程和iframe加载的过程是怎样的关系了,具体点就是父页面是否是要等待iframe页面里全部资源加载完毕后才会触发onload事件,页面的onload事件触发了,也就表明页面的忙指示结束,而忙指示是咱们衡量页面是否被阻塞的一个重要标志。java
幸运的是有人已经帮咱们作了这个实验,下面我来描述下这个实验的方式:web
阻塞加载方式即在页面直接写:chrome
<iframe src=”url”></iframe>
Iframe的url指向的页面分为四种类型:apache
1.url指向一个空文档,空文档不是指页面指向的网页不存在,而是指向网页里只有最基本的html,例如:跨域
<html><head></head><body><p>ddddd</p></body></html>
这时候iframe加载就不会由于内部静态资源而被阻塞。浏览器
2.url指向的页面里包含图片;
3.url指向的页面包含外部脚本;
4.url指向的页面包含外部css样式文件。
上面的静态资源,实验设计者都让它们的加载有延时,实验的结果是使人失望的,这些静态资源加载都会阻塞父页面的加载,即iframe的加载延长了忙指示结束的时间。
接下来实验者又作了一个实验,这个时候在父页面里iframe的src设为空,而后使用javascript代码给iframe设定src的值,赋值的时机也是在onload事件以前,而url指向和上个实验一致,结果是在以webkit为内核的safari和chrome下,页面加载明显变快,iframe的加载没有阻塞父页面的加载,可是在其余浏览器下这个结果是使人失望的,阻塞任然存在,甚至比之前还要严重。
Iframe的加载是能阻塞父页面的加载,上面朋友的现象描述里:一个iframe没有加载完毕,用户可能就会选择另一个iframe,另外一个iframe也在加载新页面,这个描述说明了,这个朋友的iframe的src应该都是使用javascript设置,而不是事先填好的,他的场景符合实验二的状况。这里又会产生一个问题,第一个iframe多是和主页面资源加载同步的,即主页面颇有可能还没触发onload事件,为啥用户还能触发iframe的加载操做,按我原来的逻辑,这时候页面应该是不能接收任何响应的,这里我要纠正下这个观点,页面被阻塞不表明页面会中止接收用户的所作的相关操做,例如在ie浏览器,若是页面被阻塞,用户点击了两次按钮,浏览器会认为用户的操做是有效的,会将用户的操做加入到浏览器执行的UI线程里的,这是浏览器对于性能不佳网页的一个妥协作法。
Iframe阻塞页面加载的问题还有更多深层次的缘由,首先iframe页面dom元素中加载最慢的,你们能够看看下面这张图:
咱们使用dom在页面里建立iframe、a、div、srcipt和style节点,第一栏是建立10个节点,第二栏是建立100个节点,第三栏是建立1000个节点,数值是表明建立的时间,因而可知建立iframe越多,耗时越长,可见iframe自己就是页面性能的瓶颈所在。
在前面文章里我讲到网站为了提高页面资源并行下载的,能够将通用的静态资源放到一个独立的域名下,跨域能够增长页面链接数,使用iframe的页面会有两个url,iframe能达到增长并行下载的目的吗?若是iframe的url和父页面的url不一样,能不能增长我没有作过测试,没法回答,可是针对这个朋友的问题,他使用的iframe的url确定会和父页面在同一个域下面,由于他使用的iframe目的是为了布局而不是为了嵌入其余web的页面,iframe和父页面同域的结果就是并发链接数是不能被增长的,由于iframe是指向一个完整的页面,在加上上面说的iframe其实也会阻塞页面的加载,所以这个场景下就等于浏览器同时加载两个独立页面却要遵照一个页面加载的方案,结果天然是页面会变得更慢。
因为这个朋友的应用是内部的控制台,所以它的网站绝对不会有作那些提高网站性能的优化工做,网站优化里有一条就是:将外部的css文件和js文件缓存,因此这个朋友网站确定会出现这个问题,第一个iframe还没加载完,用户打开了第二个iframe,这两个iframe使用的外部css文件和js文件可能大部分相同,可是它们在每一个iframe里都会被从新加载,并且第一个iframe没有加载完毕,还会阻塞第二个iframe对静态资源的加载,若是开启的iframe越多,阻塞就越加严重,后果天然也是网站愈来愈慢。
那么咱们该怎么帮这个朋友解决他的问题了?最好的方式就是将iframe去掉,使用div来实现选项卡,这么作太残酷,要重构整个前端代码,这个朋友问个人目的就是不想这么干了。
因此要考虑下代价较少的方法,下面是我晚上想到的,但愿看了我博客的大牛们也会有更多更好的建议,我想到的以下:
文章写毕,最后再重申一下但愿有大牛看了本人的文章,能告诉咱们更多更好的方式。