1. 程式人生 > >Script標籤為什麼要放在body標籤的底部?以及無阻塞下載JavaScript的幾種方法

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》