我们会经常使用iframes来加载第三方的内容、广告或者插件。使用iframe是因为它可以和主页面并行加载,不会阻塞主页面。当然使用iframe也是有利有弊的:Steve Souders在他的blog里面有阐述:Using Iframes Sparingly:

  • iframe会阻塞主页面的onload事件
  • 主页面和iframe共享同一个连接池

  阻塞主页面的onload是这两个问题中最影响性能的方面。一般都是想让onload时间越早触发越好,一方面是用户体验过更重要的是google给网站的加载速度的打分:用户可以用IE和FF中Google工具栏来计时。

  那么为了提高页面性能,怎样才能不阻塞主页面的onload事件的来加载iframe呢?

  这篇讲了四种加载iframe的方法:普通iframe,onload 之后加载iframe,setTimeout() iframe和异步加载iframe。每种方法的加载结果我都用IE8的时间线来展示。我建议多注意下动态异步加载这个方法,因为这是性能表现最佳的。另 外,还有一种友好iframe(friendly iframe)技术。它可能算不上是iframe加载的技术,但是必须使用iframe,它是无阻塞加载的。

  普通方法加载iframe

  这是一种人尽皆知的普通加载方法,它没有浏览器的兼容性问题。

<iframe src="/path/to/file" frameborder="0" width="728" height="90" scrolling="auto"></iframe>

  使用这种加载方法会在各浏览器中有如下表现:

  • iframe会在主页面的onload之前加载
  • iframe会在所有iframe的内容都加载完毕之后触发iframe的onload
  • 主页面的onload会在iframes的onload触发之后触发,所以iframe会阻塞主页面的加载。
  • 当iframe在加载的过程中,浏览器会标识正在加载东西,处于忙碌状态。

  这里是一个演示页面,时间线图显示出iframe会阻塞主页面的加载。

我的建议:注意on

load 阻塞。如果iframe的内容只需要很短的时间来加载和执行,那么也不是个大问题,而且使用这种方法还有个好处是可以和主页面并行加载。但是如果加载这个 iframe需要很长时间,用户体验就很差了。你得自己测试一下,然后在 http://www.webpagetest.org/ 也做些测试,根据onload的时间看看是否需要其他加载方法。

  在onload之后加载iframe

  如果你想在iframe中加载一些内容,但是这些内容对于页面来说不是那么的重要。或者这些内容不需要马上展现给用户的,需要点击触发之类的。那么可以考虑在主页面载入之后加载iframe。

 <script>
//doesn't block the load event
function createIframe() {
var i = document.createElement("iframe");
i.src ="path/to/file";
i.scrolling ="auto";
i.frameborder ="0";
i.width ="200px";
i.height ="100px";
document.getElementById("div-that-holds-the-iframe").appendChild(i);
};
// Check for browser support of event handling capability
if (window.addEventListener) window.addEventListener("load", createIframe, false);
else if (window.attachEvent) window.attachEvent("onload", createIframe);
else window.onload = createIframe;
</script>

这种加载方法也是没有浏览器的兼容性问题的:

  • iframe会在主页面onload之后开始加载
  • 主页面的onload事件触发与iframe无关,所以iframe不会阻塞加载。
  • 当iframe加载的时候,浏览器会标识正在加载。

  这是是一个测试页面,时间线图如下

这种方法比普通方法有什么好处呢?load事件会马上触发,有两个好处:

  • 其他等待主页面onload事件的代码可以尽早执行
  • Google Toolbar计算你页面加载的时间会大大减少

  但是,当iframe加载的时候,还是会看到浏览器的忙碌状态,相对于普通加载方法,用户看到忙碌状态的时间更长。还有就是用户还没等到页面完全加载完的时候就已经离开了。有些情况下这是个问题,比如广告。

  setTimeout()来加载iframe

  这种方法的目的是不阻塞onload事件。

  Steve Souders(又是他?)有一个这种方法的测试页面(http://stevesouders.com/efws/iframe-onload-nonblocking.php)。他写道:“src通过setTimeout动态的设置,这种方法可以在所有的浏览器中避免阻塞”。

<iframe id="iframe1" src="" width="200" height="100" border="2">
</iframe>
<script>
function setIframeSrc() {
var s ="path/to/file";
var iframe1 = document.getElementById('iframe1');
if (-1 == navigator.userAgent.indexOf("MSIE")) {
iframe1.src = s;
} else {
iframe1.location = s;
}
}
setTimeout(setIframeSrc, 5);
</script>

  在除了IE8以外的所有浏览器中会有如下表现:

  • iframe会在主页面onload之前开始加载
  • iframe的onload事件会在iframe的内容都加载完毕之后触发
  • iframe不会阻塞主页面的onload事件(IE8除外)
  • 为什么不会阻塞主页面的onload呢(IE8除外)?因为setTimeout()
  • 当iframe加载的时候,浏览器会显示忙碌状态。

  下面是时间线图:

因为IE8的问题,这种技术就不适合很多网站了。如果有超过10%的用户使用IE8, 十分之一的用户体验就会差。你会说那也只是比普通加载差一点点,其实普通加载性能上也不差。on

load事件对于10%的用户来说都更长。。。。额,你自己考虑吧。但是最好在看了下面这个很赞的异步加载方法之后再决定吧。

   我在参加Velocity 2010的时候,Meebo的两个工程师(@marcuswestin and Martin Hunt)做了一个关于他们的Meebo Bar的演讲。他们使用iframe来加载一些插件,并且真正做到了无阻塞加载。对于有的开发者来说,他们的做法还比较新鲜。很赞,超级赞。但是一些原因 导致这种技术没有得到相应的关注,我希望这篇blog能把它发扬光大。

<script>
(function(d) {
var iframe = d.body.appendChild(d.createElement('iframe')),
doc = iframe.contentWindow.document;
// style the iframe with some CSS
iframe.style.cssText ="position:absolute;width:200px;height:100px;left:0px;";
doc.open().write('<body onload="'+
  'var d = document;d.getElementsByTagName(\'head\')[0].'+
  'appendChild(d.createElement(\'script\')).src'+'=\'\/path\/to\/file\'">');
doc.close(); //iframe onload event happens
})(document);
</script>

  神奇的地方就在<body onload="">:这个iframe一开始没有内容,所以onload会立即触发。然后你创建一个script元素,用他来加载内容、广告、插件什么的,然后再把这个script添加到HEAD中去,这样iframe内容的加载就不会阻塞主页面的onload!你应该看看他在个浏览器中的表现:

  • iframe会在主页面onload之前开始加载
  • iframe的onload会立即触发,因为iframe的内容一开始为空。
  • 主页面的onload不会被阻塞
  • 为什么这个iframe不会阻塞主页面的onload?因为<body onload="">
  • 如果你不在iframe使用onload监听,那么iframe的加载就会阻塞主页面的onload。
  • 当iframe加载的时候,浏览器终于不显示忙碌状态了(非常好)

  我的测试页给出下面的时间线:

转义字符让代码看着有些难受,这都不是问题。试试吧。

  友好型iframe加载

  这是用来加载广告的。虽然这不是一种iframe的加载技术,但是是用iframe来盛放广告的。他的亮点不在于iframe如何加载,而是主页面、iframe、广告如何协同工作的。如下:

  • 先创建一个iframe,设置他的src为一个相同域名下的静态html文件。
  • 在这个iframe里面,设置js变量inDapIF=true来告诉广告它已经加载在这个iframe里面了。
  • 在这个iframe里面,创建一个script元素加上广告的url作为src,然后像普通广告代码一样加载。
  • 当广告加载完成,重置iframe大小来适应广告。
  • 这种方法也没有浏览器的兼容性问题。

  Ad Ops Council在推荐过这个方法,AOL也是用这种方法。想看看源码:这里有一个。一家瑞典的出版社Aftonbladet对于这种加载有很不错的结论:在他们的主页上,加载时间减少30%,用户每周增加7%,新闻部分的点击量增加35%。我建议可以看看他们的资料:High Performance Web Sites, With Ads: Don’t let third parties make you slow

  我没有创建相关的测试页,所以也没有第一首的资料。从我调研的结果来说:

  如果你只想在你的网页上调用一个确定的src地址的iframe的话这个方法不是很有用。

  如果你想在网页上展示多个广告,比较灵活的方法的是:加载一个广告,然后更新iframe加载另一个主页面的DOMContentLoaded时间不会被阻塞,页面渲染也不会被阻塞,当然,主页面的onload事件还是会被阻塞。

iframe异步加载技术及性能的更多相关文章

  1. Vue中router路由异步加载组件-优化性能

    何时使用异步加载组件 当首页app.js文件太大时,可以拆分组件异步加载,如果app.js文件很小时,不建议使用异步加载组件,因为异步加载组件时每次都要发送一个HTTP请求,这样的代价远比首页一次性加 ...

  2. iframe加载方案及性能

    普通方法加载iframe 在onload之后加载iframe setTimeout来加载iframe 友好型iframe加载 转载地址:翻译文章-iframe异步加载技术及性能 英文原文:Iframe ...

  3. js异步加载的解决方案

    默认情况javascript是同步加载的,javascript的加载时阻塞的,后面的元素要等待javascript加载完毕后才能进行再加载,如何解决这个问题呢,接下来将为你详细介绍下异步加载js三种实 ...

  4. 高性能页面加载技术--BigPipe设计原理及Java简单实现

    1.技术背景 动态web网站的历史可以追溯到万维网初期,相比于静态网站,动态网站提供了强大的可交互功能.经过几十年的发展,动态网站在互动性和页面显示效果上有了很大的提升,但是对于网站动态网站的整体页面 ...

  5. Scrapy爬取Ajax(异步加载)网页实例——简书付费连载

    这两天学习了Scrapy爬虫框架的基本使用,练习的例子爬取的都是传统的直接加载完网页的内容,就想试试爬取用Ajax技术加载的网页. 这里以简书里的优选连载网页为例分享一下我的爬取过程. 网址为: ht ...

  6. [翻译]Bitmap的异步加载和缓存

    内容概述 [翻译]开发文档:android Bitmap的高效使用 本文内容来自开发文档"Traning > Displaying Bitmaps Efficiently", ...

  7. 异步加载js文件的方法

    # 异步加载js文件 - js的加载默认是同步的,因为js是单线程执行,只能完成一件再执行下一件. - 一些外部引入的js文件可以因为文件太大,在加载资源的过程中会影响dom元素的加载,影响了用户体验 ...

  8. 抛砖引玉:探讨网站性能优化之Javascript异步懒加载技术

    懒加载技术是现在许多大型网站的都使用的提高网站性能的方式,它的核心思想是当用户想看页面某个区域时,再加载该区域的数据.这在一定程度上减轻了服务器端的压力,也加快了页面的呈现速度. 其实国内很多网站都用 ...

  9. 异步加载script,提高前端性能(defer和async属性的区别)

    一.异步加载script的好处 为了加快首屏响应速度,前端会采用代码切割.按需加载等方式优化性能.异步加载script也是一种前端优化的手段. 就好比如果我的页面其中一个功能需要打开地图,但是地图的j ...

随机推荐

  1. 哈哈:sqlserver2008附加数据库时操作系统错误5(拒绝访问)错误5012的解决办法

    老师说:无论干什么,出错了,先大笑三声.如果人多了,在心里也要大笑三声.哈哈哈!!! 刚刚重装系统完后,然后想学习.自己去安装sqlserver2008数据库,完之后想附加之前的数据库.可是当我一点确 ...

  2. 转载 CSS3 经典教程系列:CSS3 盒阴影(box-shadow)详解

    目标大纲 文章转载 CSS3 经典教程系列:CSS3 盒阴影(box-shadow)详解 IE中CSS-filter滤镜小知识大全 CSS实现跨浏览器兼容性的盒阴影效果

  3. require的总结

    前言 我们来看原生的API吧: http://www.requirejs.org/docs/api.html#config 加载javascript文件 RequireJS采用不同的方法来加载脚本,他 ...

  4. js自建方法库(持续更新)

    1.得到一个数,在一个有序数组中应该排在的位置序号: function orderInArr(num,arr) { if(num > arr[0]){ return 1 + arguments. ...

  5. jquery-懒加载技术(简称lazyload)

    第一:lazyLoad简介及作用 网站性能优化的插件,提高用户体验. 页面如果有很多图片的时候,当你滚动到相应的行时,当前行的图片才即时加载的,这样子的话页面在打开只加可视区域的图片,而其它隐藏的图片 ...

  6. Android编码规范04

    private final String MESSAGE_WARN = "您输入的密码有误,请重新输入!"; private final String CLASS_ONE = &q ...

  7. 利用Maven把项目生成jar包供其他项目使用

    每当搭建框架时,第一步就是为系统整理一个接一个的jar包.用多了就开始深思,如何把自己的项目也整成jar包,供他人使用呢? 近期一直在看徐晓斌所著:<Maven实战>.因自己学识不够,只是 ...

  8. ajax参数设置略解

    通过ajax可以直接由页面访问到服务器.做到不刷新页面,就能刷新数据,为开发带来很大的便利. 1.ajax方式的参数及其功能: $.ajax({ type : "POST", // ...

  9. crontab -e 每天定时备份mysql

    contab -e 00 03 * * * mysqldump -u juandx --password=wenbin -d 'juandx$blog' -h host > /home/juan ...

  10. MongoDB学习笔记~环境搭建

    回到目录 Redis学习笔记已经告一段落,Redis仓储也已经实现了,对于key/value结构的redis我更愿意使用它来实现数据集的缓存机制,而对于结构灵活,查询效率高的时候使用redis就有点不 ...