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