iframe異步加載技術及性能

發布時間:2011年08月24日      浏覽次數:686 次
我(wǒ)(wǒ)們會經常使用iframes來加載第三方的内容、廣告或者插件。使用iframe是因爲他可以和主頁面并行加載,不會阻塞主頁面。當然使用iframe也是有利有弊的:Steve Souders在他的blog裏面有闡述:Using Iframes Sparignly: src="static/picture/20170711122112.jpg"
iframe會阻塞主頁面的onload事件
主頁面和iframe共享同一(yī)個連接池
阻塞主頁面的onload是這兩個問題中(zhōng)最影響性能的方面。一(yī)般都是想讓onload時間越早觸發越好,一(yī)方面是用戶體(tǐ)驗過更重要的是google給網站的加載速度的打分(fēn):用戶可以用IE和FF中(zhōng)Google工(gōng)具欄來計時。
那麽爲了提高頁面性能,怎樣才能不阻塞主頁面的onload事件的來加載iframe呢?
這篇講了四種加載iframe的方法:普通iframe,onload之後加載iframe,setTimeout() iframe和異步加載iframe。每種方法的加載結果我(wǒ)(wǒ)都用IE8的時間線來展示。我(wǒ)(wǒ)建議多注意下(xià)動态異步加載這個方法,因爲這是性能表現最佳的。另外(wài),還有一(yī)種友好iframe(friendly iframe)技術。他可能算不上是iframe加載的技術,但是必須使用iframe,他是無阻塞加載的。
普通方法加載iframe
這是一(yī)種人盡皆知(zhī)的普通加載方法,它沒有浏覽器的兼容性問題。
<iframe src="/path/to/file" frameborder="0" width="728" height="90" scrolling="auto"> </iframe>使用這種加載方法會在各浏覽器中(zhōng)有如下(xià)表現:
iframe會在主頁面的onload之前加載
iframe會在所有iframe的内容都加載完畢之後觸發iframe的onload
主頁面的onload會在iframes的onload觸發之後觸發,所以iframe會阻塞主頁面的加載
當iframe在加載的過程中(zhōng),浏覽器的會标識正在加載東西,處于忙碌狀态。
這裏是一(yī)個演示頁面,時間線圖顯示出iframe會阻塞主頁面的加載。

我(wǒ)(wǒ)的建議:注意onload阻塞。如果iframe的内容隻需要很短的時間來加載和執行,那麽也不是個大(dà)問題,而且使用這種方法還有個好處是可以和主頁面并行加載。但是如果加載這個iframe需要很長時間,用戶體(tǐ)驗就很差了。你得自己測試一(yī)下(xià)然後在http://www.webpagetest.org/也做些測試,根據onload的時間看看是否需要其他加載方法。
在onload之後加載iframe
如果你想在iframe中(zhōng)加載一(yī)些内容,但是這些内容對于頁面來說不是那麽的重要。或者這些内容不需要馬上展現給用戶的,需要點擊觸發之類的。那麽可以考慮在主頁面載入之後加載iframe。
===============================================
個人感覺以下(xià)這種方式不錯,将div放(fàng)在要顯示的位置,把javascript代碼放(fàng)在網頁的最底部執行
===============================================
<div id="test_div"></div>
<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("test_div").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之後開(kāi)始加載
主頁面的onload事件觸發與iframe無關,所以iframe不會阻塞加載
當iframe加載的時候,浏覽器會标識正在加載
這是是一(yī)個測試頁面,時間線圖如下(xià)

這種方法比普通方法有什麽好處呢?load事件會馬上觸發,有兩個好處:
其他等待主頁面onload事件的代碼可以盡早執行
Google Toolbar計算你頁面加載的時間會大(dà)大(dà)減少
但是,當iframe加載的時候,還是會看到浏覽器的忙碌狀态,相對于普通加載方法,用戶看到忙碌狀态的時間更長。還有就是用戶還沒等到頁面完全加載完的時候就已經離(lí)開(kāi)了。有些情況下(xià)這是個問題,比如廣告。
setTimeout()來加載iframe
這種方法的目的是不阻塞onload事件。
Steve Souders(又(yòu)是他?)有一(yī)個這種方法的測試頁面(http://stevesouders.com/efws/iframe-onload-nonblocking.php)。他寫道:“src通過setTimeout動态的設置,這種方法可以再所有的浏覽器中(zhōng)避免阻塞”。
<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以外(wài)的所有浏覽器中(zhōng)會有如下(xià)表現:
iframe會在主頁面onload之前開(kāi)始加載
iframe的onload事件會在iframe的内容都加載完畢之後觸發
iframe不會阻塞主頁面的onload事件(IE8除外(wài))
爲什麽不會阻塞主頁面的onload呢(IE8除外(wài))?因爲setTimeout()
當iframe加載的時候,浏覽器會顯示忙碌狀态
下(xià)面是時間線圖

因爲IE8的問題,這種技術就不适合很多網站了。如果有超過10%的用戶使用IE8,十分(fēn)之一(yī)的用戶體(tǐ)驗就會差。你會說那也隻是比普通加載差一(yī)點點,其實普通加載性能上也不差。onload事件對于10%的用戶來說都更長。。。。額,你自己考慮吧。但是最好在看了下(xià)面這個很贊的異步加載方法之後再決定吧。
我(wǒ)(wǒ)在參加Velocity 2010的時候,Meebo的兩個工(gōng)程師(@marcuswestin and Martin Hunt)做了一(yī)個關于他們的Meebo Bar的演講。他們使用iframe來加載一(yī)些插件,并且真正做到了無阻塞加載。對于有的開(kāi)發者來說,他們的做法還比較新鮮。很贊,超級贊。但是一(yī)些原因導緻這種技術沒有得到相應的關注,我(wǒ)(wǒ)希望這篇blog能把它發揚光大(dà)。
<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一(yī)開(kāi)始沒有内容,所以onload會立即觸發。然後你創建一(yī)個script元素,用他來加載内容、廣告、插件什麽的,然後再把這個script添加到HEAD中(zhōng)去(qù),這樣iframe内容的加載就不會阻塞主頁面的onload!你應該看看他在個浏覽器中(zhōng)的表現:
iframe會在主頁面onload之前開(kāi)始加載
iframe的onload會立即觸發,因爲iframe的内容一(yī)開(kāi)始爲空
主頁面的onload不會被阻塞
爲什麽這個iframe不會阻塞主頁面的onload?因爲<body onload=”">
如果你不在iframe使用onload監聽(tīng),那麽iframe的加載就會阻塞主頁面的onload
當iframe加載的時候,浏覽器終于不顯示忙碌狀态了(非常好)
我(wǒ)(wǒ)的測試頁給出下(xià)面的時間線:

轉義字符讓代碼看着有些難受,這都不是問題。試試吧。
友好型iframe加載
這是用來加載廣告的。雖然這不是一(yī)種iframe的加載技術,但是是用iframe來盛放(fàng)廣告的。他的亮點不在于iframe如何加載,而是主頁面、iframe、廣告如何協同工(gōng)作的。如下(xià):
先創建一(yī)個iframe。設置他的src爲一(yī)個相同域名下(xià)的靜态html文件
在這個iframe裏面,設置js變量inDapIF=true來告訴廣告它已經加載在這個iframe裏面了
在這個iframe裏面,創建一(yī)個script元素加上廣告的url作爲src,然後像普通廣告代碼一(yī)樣加載
當廣告加載完成,重置iframe大(dà)小(xiǎo)來适應廣告
這種方法也沒有浏覽器的兼容性問題。
Ad Ops Council在推薦過這個方法,AOL也是用這種方法。想看看源碼:這裏有一(yī)個。一(yī)家瑞典的出版社Aftonbladet對于這種加載有很不錯的結論:在他們的主頁上,加載時間減少30%,用戶每周增加7%,新聞部分(fēn)的點擊量增加35%。我(wǒ)(wǒ)建議可以看看他們的資(zī)料:High Performance Web Sites, With Ads: Don’t let third parties make you slow
我(wǒ)(wǒ)沒有創建相關的測試頁,所以也沒有第一(yī)首的資(zī)料。從我(wǒ)(wǒ)調研的結果來說:
如果你隻想在你的網頁上調用一(yī)個确定的src地址的iframe的話(huà)這個方法不是很有用。
如果你想在網頁上展示多個廣告,比較靈活的方法的是:加載一(yī)個廣告,然後更新iframe加載另一(yī)個主頁面的DOMContentLoaded時間不會被阻塞,頁面渲染也不會被阻塞,當然,主頁面的onload事件還是會被阻塞。
免責聲明:本站相關技術文章信息部分(fēn)來自網絡,目的主要是傳播更多信息,如果您認爲本站的某些信息侵犯了您的版權,請與我(wǒ)(wǒ)們聯系,我(wǒ)(wǒ)們會即時妥善的處理,謝謝合作!