Script標籤為什麼要放在body標籤的底部?以及無阻塞下載JavaScript的幾種方法
指令碼位置
瀏覽器在解析到<body>標籤之前,不會渲染頁面的任何部分。把指令碼放到頁面頂部會導致明顯的延遲,通常表現為顯示空白頁面,使用者無法瀏覽內容,也無法和頁面進行互動。
儘管IE8,FX3.5,Safari4和Chrome2+都允許並行下載JavaScript檔案。這樣<script>標籤在下載外部資源時不會阻塞其他<script>標籤。遺憾的是,JavaScript下載過程中任然會阻塞其他資源的下載,比如圖片。
由於指令碼會阻塞其他資源的下載,因此推薦將所有<script>標籤儘可能放到<body>標籤的底部,以儘量減少對整個頁面下載的影響。
組織指令碼
由於每個<script>標籤初始下載時都會阻塞頁面渲染,所以減少頁面包含<script>標籤數量有助於改善這一情況。這不僅僅針對外鏈指令碼,內嵌指令碼的數量也要同樣的限制。瀏覽器在解析HTML頁面的過程中每遇到一個<script>標籤,都會因執行指令碼而導致一定的延遲,因此最小化延遲時間將會明顯地改善頁面的效能。
因此下載單個100kb的檔案比下載4個25kb的檔案更快。
無阻塞下載JavaScript的方法
延遲的指令碼
HTML4為<script>標籤定義了一個拓展屬性:defer。Defer屬性指明本元素所含的指令碼不會修改DOM,因此程式碼能夠安全地延遲執行。對應的JavaScript檔案將在頁面解析到這個<script>標籤時開始下載,但不執行,直到DOM下載完成(onload事件被觸發前)
經過我的測試發現只有在外鏈指令碼時defer才起到作用,內嵌指令碼沒有起到作用,我用的瀏覽器為Chrome。
HTML:
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> </head> <body> <script src="../../../Scripts/javascript/PO/defer.js" defer></script> <script src="../../../Scripts/javascript/PO/defer2.js"></script> <script> window.onload = function (event) { alert("onload "); } </script> </body> </html>
defer.js:
alert("defer")
defer2.js:
alert("before onload");
動態建立指令碼
動態建立script指令碼後,檔案會在被新增到頁面時立即下載。它的重點在於:檔案的下載和執行過程不會阻塞頁面其他程序,在下載檔案時裡面的程式碼會立即執行。
這種情況下,當下載的程式碼包含其他指令碼要呼叫的介面或者方法時,就會有問題,所以我們需要跟蹤並確保指令碼下載完畢且準備就緒。FX,Opera,Chrome和Safari 3+的版本會在script元素接收完成時觸發load事件,因此,你可以通過監聽此事件來判斷是否下載完畢。
具體程式碼如下:
function loadScript(url, callback) {
var script = document.createElement("script");
script.type = "text/javascript";
script.src = url;
script.onload = function () {
callback();
};
document.getElementsByTagName("head")[0].appendChild(script);
}
以上內容來自《高效能JavaScript》