DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> JavaScript入門知識 >> JavaScript基礎知識 >> 高性能JavaScript-JS腳本加載與執行對性能的影響
高性能JavaScript-JS腳本加載與執行對性能的影響
編輯:JavaScript基礎知識     

在web產品優化准則中,很重要的一條是針對js腳本的加載和執行方式的優化。本篇文章簡單描述一下其中的優化准則。

1. 腳本加載優化

1.1 腳本位置對性能的影響

優化頁面加載性能的原則之一是將script標簽放在body底部,這跟浏覽器的渲染原理有關:

  1. js腳本的下載和執行會阻塞浏覽器的解析。在較早時期,浏覽器不支持並行下載的時候,js腳本的下載執行按照在html文檔中的位置依次進行,可以想象當頁面有大量js腳本時頁面的加載有多慢;
  2. js腳本的下載會阻塞其他資源的下載,比如圖片、外鏈css等。雖然目前大多數浏覽器支持並行下載,外鏈js文件可以並行下載,但是在下載js的過程中,其他資源的加載仍然會被阻塞。

綜上所述,除非業務需求必須將js腳本放在指定位置,最佳的優化准則是將js放於body底部。

1.2 合並腳本文件

每個script標簽都會阻塞頁面的解析和其他資源的加載,可以通過合並js腳本文件進行優化。雖然目前大多數浏覽器支持並行下載,但是隨著web產品越來越龐大,浏覽器支持的並行數量明顯不能滿足需求,隨意js文件的合並打包是很有必要的。

目前較流行的grunt/gulp/webpack等編譯工具都支持文件的打包合並,webpack甚至可以將css文件也一並打包到js文件裡。我們先不去評價這種模式的好壞,單從減少文件數量這個角度來看,這是為了減少http請求數目、script標簽數量以提高頁面的加載性能。

其實這種理念很早就有,有後端開發經驗的朋友可能接觸過combo handler,這是Yahoo YUI團隊開發的一個Apacha模塊。combo handler可以支持浏覽器使用一個url請求多個文件,比如我們頁面中需要兩個js文件,常規情況下使用2個script標簽請求:

<script src='http://static.me.com/a.js'></script>
<script src='http://static.me.com/b.js'></script>

使用combo handler可以通過以下形式:

<script src='http://static.me.com?a.js&b.js'></script>

a.js和b.js在服務器是獨立存在的,combo handler可以通過一個http請求將兩者合並為一起返回,減少了http請求數目,提高了頁面加載性能。

2. 無阻塞腳本

2.1 defer和async

defer和async都是針對外鏈的js腳本文件,如下:

<script src='http://static.me.com/a.js' defer></script>
<script src='http://static.me.com/a.js' async></script>

defer和async的作用都是令指定的js文件異步加載,不影響html文檔其他內容的解析,也就是說帶有defer和async的js文件和html文檔的解析是並行的。但是兩者的運行機制有稍許差別。

defer在IE4就引入了,目前幾乎所有浏覽器都支持。defer的js文件在並行下載結束後並不立即執行,其執行時機是在文檔加載完畢後window.onload觸發之前

async是HTML5引入的新規范,目前獲得了大多數浏覽器的支持。async的js文件在並行下載結束後立即執行

比較defer和async的區別可以得到以下結論:

  1. 兩者都是並行下載,不影響html文檔的解析;
  2. defer文件的執行時機是在window.onload之前,所以defer文件的位置任意;
  3. async文件下載結束後立即執行,是亂序的。所以並不適用於有依賴關系的js腳本;
  4. defer和async的腳本中應當避免使用document.wirte,否則會清空頁面原有的內容。
2.2 動態腳本

所謂動態腳本的意思是使用JavaScript創建一個script,指定其src並將此script標簽插入文檔的head中。

之所以將動態script標簽插入head而不是body中是因為在低版本IE中如果在html文檔未解析完畢時,body中插入script標簽會拋出“操作已終止”的錯誤信息。具體可參考The dreaded Operation Aborted error。

動態腳本請求到的js腳本是立即執行的。

動態創建script標簽時,某些業務場景下需要監聽被請求的js腳本是否加載完畢。大多數浏覽器都支持script.onload事件:

script.onload = function(){}

IE浏覽器沒有實現onload事件,而是會觸發readystatechange事件。當readyState的狀態為loadedcomplete時便可以認為js腳本文件已加載完畢。兼容所有浏覽器的loadScript函數如下:

function loadScript(url,callbakc){
    var script = document.createElement('script');
    script.type = 'text/javascript'; //低版本IE下必須制定type,其他浏覽器可以不寫

    if(script.readtState){ //IE
        script.onreadystatechange = function(){
            if(script.readyState === 'loaded' || script.readyState === 'complete'){
                script.readyState === 'null';
                callback();
            }
        };
    }else{ //其他浏覽器
        script.onload = function(){
            callbakc();
        }
    }
    
    script.src = url;
    document.getElementByTagName('head')[0].appendChild(script);
}
2.3 使用XHR注入js腳本

使用XHR注入腳本是比較偏門並且應用面很小的一門技術,原理就是用Ajax去get請求一個js文件,監聽xhr.status,獲取到的響應信息是js文件的代碼。然後動態創建一個script標簽,將獲取到的js代碼注入script標簽內,最後將script標簽插入文檔中。

這種方式注入的js腳步並不會立即執行。缺點是無法跨域,因此很少得到應用。

XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved