腳本的阻塞特性:把腳本放在底部
<script>標簽因腳本的加載,解析,運行而暫時整個頁面的下載和解析過程。如果把它放在<head>標簽里面。通常表現為:頁面打開時,首先顯示為一副空白的頁面。
因為腳本阻塞其他頁面資源的下載,所以推薦的方法就是:將所有的<script>標簽放在盡可能接近<body>標簽底部的位置即</body>之前。盡量減少對整個頁面下載的影響。
減少腳本的數量
當頁面解析每碰到一個<script>時,緊接着都會有一段時間用於js代碼的運行,最小化這些延遲時間可以改善頁面的性能。另外,對於外部js文件,會發出http請求,每個http請求都會產生額外的性能,下載一個100k的js文件要比下載4個25k的js文件要快,所以合並js有助於改善頁面的性能。
精簡js源代碼及壓縮腳本(gzip)
精簡js源代碼是指去除一個js文件中一切與運行無關的內容,包括注釋和不必要的空格,使js源文件體積更小,下載更快。推薦使用JSMin和Dojo Compressor;壓縮腳本需要在服務器做相應的配置,同樣適用於樣式表。
非阻塞加載腳本
非阻塞加載腳本是等頁面加載完后再加載Javascript源碼。從技術角度來說,這意味着在window的load事件發出后開始下載腳本。
延遲腳本:HTML4為<script>添加了一個defer屬性,這個屬性指明該腳本不會修改DOM,所以代碼可以稍后執行。僅IE和FF3.5支持,其他瀏覽器依然阻塞。代碼如下
<script type="text/javascript" src="file.js" defer="defer"></script>
任何支持帶有defer屬性的<script>元素在DOM加載完之前是不會被執行的,不管是內聯腳本還是外部文件,所以它可以放到頁面的任何位置。
動態添加腳本元素:<script>元素與其它元素一樣,可以通過Javascript從文檔中添加,移動,刪除。代碼如下
1 var script = document.createElement("script"); 2 script.type = "text/javascript"; 3 script.onload=function(){ 4 //表示已經加載完 5 }; 6 script.src = "file.js"; 7 document.getElementsByTagName("head")[0].appendChild(script);
file.js文件當元素添加到頁面后立刻開始下載,重點在於無論在何處啟動下載,文件的下載和運行都不會阻塞其他頁面資源的處理。因為可能要經常使用到,所以可以封裝成一個跨瀏覽器的函數,方便以后使用:
1 function asyncLoadScript(url,callback){ 2 var script = document.createElement("script"); 3 script.type = "text/javascript"; 4 if(script.readyState){//ie 5 script.onreadystatechange = function(){ 6 if(script.readyState == "loaded" || script.readyState == "complete"){ 7 script.onreadystatechange = null; 8 callback(); 9 } 10 } 11 }else{//other 12 script.onload = function(){ 13 callback(); 14 }; 15 } 16 script.src = url; 17 document.body.appendChild(script); 18 } 19 //加載多個js,保證其順序 20 asyncLoadScript("file1.js",function(){ 21 asyncLoadScript("file2.js",function(){ 22 asyncLoadScript("file3.js",function(){ 23 //所有js加載完成 24 }); 25 }); 26 });
還有一種方法就是利用XMLHttpRequest對象異步加載js文件,此方法的優點是:在js文件加載完后才創建script元素,所以它下載后不會自動執行。缺點是js文件必須與頁面放在同一個域內,不能從CDN(內容分發網絡)下載,一般來說大型網站不會使用這種方法。代碼如下:
1 //跨瀏覽器創建XHR對象 2 function createXHR(){ 3 if(typeof XMLHttpRequest != "undefined"){ 4 createXHR = function(){ 5 return new XMLHttpRequest(); 6 }; 7 }else if(typeof ActiveXObject != "undefined"){ 8 createXHR = function(){ 9 if(typeof arguments.callee.activeXString != "string"){ 10 var versions = ["MSXML2.XMLHttp.6.0","MSXML2.XMLHttp.3.0","MSXML2.XMLHttp"]; 11 for(var i=0; i<versions.length; i++){ 12 try{ 13 var xhr = new ActiveXObject(versions[i]);//試探瀏覽器支持能力 14 arguments.callee.activeXString = versions[i];//把瀏覽器支持的XHR版本保存在activeXString屬性中 15 return xhr; 16 } 17 catch(ex){ 18 //skip 19 } 20 } 21 } 22 return new ActiveXObject(arguments.callee.activeXString); 23 }; 24 }else{ 25 createXHR = function(){ 26 throw new Error("No XMLHttpRequest object available."); 27 }; 28 } 29 return createXHR(); 30 } 31 //利用XHR對象異步加載JS 32 function XHRLoadScript(url,callback){ 33 var xhr = createXHR(); 34 //為保持跨瀏覽器兼容性,必須在調用open()之前指定onreadystatechange事件處理程序 35 xhr.onreadystatechange = function(){ 36 if(xhr.readyState == 4){ 37 if(xhr.status >= 200 && xhr.status < 300 || xhr.status == 304){ 38 var script = document.createElement("script"); 39 script.type = "text/javascript"; 40 script.text = xhr.responseText; 41 document.body.appendChild(script); 42 43 callback(); 44 } 45 } 46 }; 47 xhr.open("get",url,true); 48 //盡管不發送數據,但對於某些瀏覽器來說這個參數是必需的 49 xhr.send(null); 50 51 }
使用其它庫來加載js:
1、Yahoo Search的lazyload 用法: LazyLoad.js([urlString|urlArray],function(){});
2、Kyle Simpson的LABjs 用法:$LAB.script(firstURL).script(secondURL).wait(function(){});