很讚的 Non-blocking JavaScript
前陣子將網站的所有 JavaScript 採用 Non-blocking 的方式做載入,整個介面 rendering 的時間減少很多,是我們想要的效果:
(function(){
var scriptEl = document.createElement("script");
scriptEl.src = "foo.js";
scriptEl.type = "text/javascript";
scriptEl.async = true;
document.getElementsByTagName("head")[0].appendChild(scriptEl);
}());
IE 獨有的鬼打牆問題
但是今天在 IE 發現了一個蠻嚴重的問題:「假設用 Non-blocking 的方式在 head 載入某 JavaScript ,而此 JavaScript 有指定 window 的 load 的事件處理函式,會發現它常常沒有被觸發。」
IE 對 window.onload 的時間觸發點與其他瀏覽器不同
Nicholas C. Zakas 的 The truth about non-blocking JavaScript 有提到:
These three techniques for non-blocking JavaScript ensure that the downloading of the resource doesn’t block either rendering or the download of other resources on the page during page load. The little-known or understood aspect of all three approaches is that they are all defined to block the load event. That means adding scripts using any of these techniques during page load will delay execution of the window.onload event handler until all scripts have executed. All browsers obey this behavior except for Internet Explorer (even through version 9).
中文的意思是,Non-blocking 的所有方法都會對 onload 事件造成延遲、必須要等到指定的 JavaScript 讀取完畢才會真正執行,但 IE 是唯一的例外。所以在 IE 當網頁實際讀取完畢(onload)的時間點早於 JavaScript 被執行的時間點時,JavaScript 中所撰寫的 window load 事件就不會生效了...
範例網頁:除了 IE,其他瀏覽器都會跳出 alert 訊息。
所衍生的問題
看起來,似乎我們只要避免去綁 window 的 load 事件即可,但是現在的 JavaScript 函式庫大多有做一些偵測,例如我們想要當某個 div 內容讀取完畢時就做某些動作,此時便使用 YUI 的 contentready 事件,但是 contentready 事件又會去檢查 window 的 load 事件,如果剛好又滿足前段所提的條件時,我們這個 contentready 就永遠不會被觸發。
目前只能先改用不會檢查 load 的 available 方法來達成,也在 YUI Forum 提出了這個問題。希望大家能夠幫我想想有沒有其他好解法。