iframe 异步加载技术及性能,及个人总结的预加载


我们会经常使用iframes来加载第三方的内容、广告或者插件。使用iframe是因为它可以和主页面并行加载,不会阻塞主页面。

缺点:

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

阻塞主页面的onload是这两个问题中最影响性能的方面。一般都是想让onload时间越早触发越好。

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

这篇讲了四种加载iframe的方法:

  • 普通iframe,
  • onload之后加载iframe,
  • setTimeout() iframe
  • 异步加载iframe。

每种方法的加载结果我都用IE8的时间线来展示。我建议多注意下动态异步加载这个方法,因为这是性能表现最佳的。

普通方法加载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在加载的过程中,浏览器会标识正在加载东西,处于忙碌状态。

我的建议:注意onload阻塞。如果iframe的内容只需要很短的时间来加载和执行,那么也不是个大问题,而且使用这种方法还有个好处是可以和主页面并行加载。

但是如果加载这个iframe需要很长时间,用户体验就很差了。

在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事件。

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, 十分之一的用户体验就会差。你会说那也只是比普通加载差一点点,其实普通加载性能上也不差。onload事件对于10%的用户来说都更长。。。。额,你自己考虑吧。但是最好在看了下面这个很赞的异步加载方法之后再决定吧。

异步加载iframe

<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预加载小记

这里表演的是 jquery-1.7.js 预加载,在下面的点击事件之前已经预加载好了。

(function(doc) {
    var ifr = doc.body.appendChild(doc.createElement('iframe')),
        ifr_doc = ifr.contentWindow.document;

    ifr.frameborder = '1px';
    ifr.height = '1px';
    ifr.width = '1px';
    ifr.style.display = 'none';

    var loadjs = '<body onload="' +
                 'var d = document;d.getElementsByTagName(\'head\')[0].appendChild(' +
                 'd.createElement(\'script\')).src' +
                 '=\'javascript/jquery-1.7.js\'">';

    ifr_doc.open();
    ifr_doc.write(loadjs);
    ifr_doc.close();
})(document);

$('loadBtn').addEvent('click', function() {
    var script = document.createElement('script');
    script.async = true;
    script.src = 'javascript/jquery-1.7.js';
    document.getElementsByTagName('head')[0].appendChild(script);
});

先自调用

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM