這是一篇原創翻譯文章。原文地址。
我們會經常使用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會阻塞首頁面的載入。
我的建議:注意onload阻塞。如果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,十分之一的使用者體驗就會差。你會說那也只是比普通載入差一點點,其實普通載入效能上也不差。onload事件對於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事件還是會被阻塞。
轉載請註明:
作者:
BeiYuu