詳談LABJS按需動態(tài)加載js文件
LABjs 是一個很小的 JavaScript 工具,用來根據(jù)需要加載 JavaScript 文件,通過使用該工具可以提升頁面的性能,避免加載不需用到的 JavaScript 文件,可以實現(xiàn)動態(tài)并行加載腳本文件,以及管理加載腳本文件的執(zhí)行順序。
簡單示例
$LAB
.script("script1.js", "script2.js", "script3.js")
.block(function(){
// wait for all to load, then do something
script1Func();
script2Func();
script3Func();
});
介紹下LABJS的幾個實例:
實例1:
$LAB
.script("script1.js")
.script("script2.js")
.script("script3.js")
.wait(function(){ // 等待所有script加載完再執(zhí)行這個代碼塊
script1Func();
script2Func();
script3Func();
});
實例2:
$LAB
.script({ src: "script1.js", type: "text/javascript" })
.script("script2.js")
.script("script3.js")
.wait(function(){ // 等待所有script加載完再執(zhí)行這個代碼塊
script1Func();
script2Func();
script3Func();
});
實例3:
$LAB
.script("script1.js", "script2.js", "script3.js")
.wait(function(){ // 等待所有script加載完再執(zhí)行這個代碼塊
script1Func();
script2Func();
script3Func();
});
實例4:
$LAB
.script( [ "script1.js", "script2.js" ], "script3.js")
.wait(function(){ // 等待所有script加載完再執(zhí)行這個代碼塊
script1Func();
script2Func();
script3Func();
});
實例5:
$LAB
.script("script1.js").wait() // 空的wait()只是確保script1在其他代碼之前被執(zhí)行
.script("script2.js") // script2 和 script3 依賴于 script1
.script("script3.js").wait() // 但是script2 和 script3 并不互相依賴,可以并行下載
.script("script4.js") // script4 依賴于 script1, script2 及 script3
.wait(function(){script4Func();});
實例6:
$LAB
.script("script1.js") // script1, script2, and script3 之間沒有依賴關(guān)系,
.script("script2.js") // 所以可以任意順序執(zhí)行
.script("script3.js")
.wait(function(){ // 如果需要,這里當然可以執(zhí)行javascript函數(shù)
alert("Scripts 1-3 are loaded!");
})
.script("script4.js") // 依賴于 script1, script2 及 script3
.wait(function(){script4Func();});
實例7:
$LAB
.setOptions({AlwaysPreserveOrder:true}) // 設(shè)置每個腳本之間等待
.script("script1.js") // script1, script2, script3, script4 互相依賴
.script("script2.js") // 并且并行下載后循序執(zhí)行
.script("script3.js")
.script("script4.js")
.wait(function(){script4Func();});
實例8:
$LAB
.script(function(){
// `_is_IE`的值ie為true ,非ie為false
if (_is_IE) {
return "ie.js"; // 如果是ie則這個js會被加載
}
else {
return null; //如果不是ie這個代碼就會被略過
}
})
.script("script1.js")
.wait();
LABjs加載方式
LABjs里的動態(tài)加載腳本文件,是指頁面的js腳本執(zhí)行時,通過多種方法去加載外部的js(主要區(qū)別于html頁面里,通過<script>標簽靜態(tài)加載的腳本)
動態(tài)加載腳本的方式有很多,優(yōu)缺點不一,此處不贅述,有興趣的童鞋可以參見本文末尾的參考鏈接 :)。
LABjs里主要使用了三種技巧,分別為Script Element、XHR Injection以及Cache Trick
首先對這三種加載方式進行簡單介紹,第四部分再分析LABjs源碼實現(xiàn)里面對著三種方式分別的使用場景
Script Element(LABjs默認采用加載方式)
最常見的腳本動態(tài)加載方式,優(yōu)點很多,包括:1、實現(xiàn)簡單 2、可跨域 3、不會阻塞其他資源的加載 等
Opera/Firefox(老版本)下:腳本執(zhí)行的順序與節(jié)點被插入頁面的順序一致
IE/Safari/Chrome下:執(zhí)行順序無法得到保證
注意:
新版本的Firefox下,腳本執(zhí)行的順序與插入頁面的順序不一定一致,但可通過將script標簽的async屬性設(shè)置為false來保證順序執(zhí)行
老版本的Chrome下,腳本執(zhí)行的順序與插入頁面的順序不一定一致,但可通過將script標簽的async屬性設(shè)置為false來保證順序執(zhí)行
XHR Injection
通過ajax請求加載腳本文件,然后再通過以下方式執(zhí)行:
eval:常見方式
XHR injection:創(chuàng)建一個script元素,并將請加載的腳本文件的內(nèi)容注入
主要限制:無法跨域
Cache Trick(強依賴于瀏覽器的特性實現(xiàn),不推薦使用)
當你將script元素的type屬性設(shè)置為瀏覽器不認識的值,比如”text/cache”、”text/casper”、”text/hellworld”等,不同瀏覽器的行為如下:
IE/Safari/Chrome(老版本)里:腳本照常加載,但不會執(zhí)行,假設(shè)瀏覽器沒有禁用緩存,加載后的腳本會被瀏覽器緩存起來,當需要用到 的時候,只需要重新創(chuàng)建個script標簽,將type設(shè)為正確的值,src指向之前請求的文件url即可(相當于從緩存里讀文件)
Opera/Firefox:不加載
備注:
強依賴于瀏覽器的特性實現(xiàn),有可能隨著瀏覽器特性實現(xiàn)的改變而失效,不推薦使用
新版本的chrome瀏覽器,將script元素的type設(shè)置為非”text/javascript”,不會再對腳本文件進行加載。
LABjs里關(guān)于腳本加載采用方案的判斷
忽略技術(shù)細節(jié),通過一段偽代碼來描述LABjs里面的實現(xiàn),大致為:
首先判斷是否對請求的腳本進行預加載(是否進行預加載的判斷條件看偽代碼注釋);
如進行預加載,再判斷瀏覽器是否支持真正的預加載;如支持真正的預加載,則預加載之;如否,判斷請求的腳本是否跟當前頁面同域,如實,采用XHR Injection,如否,采用Cache Trick;
如不進行預加載,判斷瀏覽器支不支持script元素的async屬性(見偽代碼注釋),如是,設(shè)置async屬性,并請求腳本文件;如否,直接通過script元素加載腳本文件;
if(ifPreloadScript){ //當請求的腳本文件是否進行預加載:1、需要預加載 2、瀏覽器支持預加載
if(supportRealPreloading){ //如果支持真正的預加載
if(supportPreloadPropNatively){ //支持通過設(shè)置script標簽的preload屬性,實現(xiàn)script的預加載,以及分離加載和執(zhí)行
//Nicholas C. Zakas大神的美好愿望,尚未有瀏覽器支持:/blog/2011/02/14/separating-javascript-download-and-execution/
script.onpreload = callback;
script.newPreload = true;
script.src = targetUrl;
}else{
script.onreadystatechange = callback; //其實就是指IE瀏覽器,假設(shè)指定了script元素的src屬性,IE瀏覽器里會立即加載
script.src = targetUrl; //即使script元素沒有被插入頁面,callback為預加載后的回調(diào)
}
}
else if(inSameDomain){ //非跨域,采用XHR Injection:請求的腳本與當前頁面處于同一個域
xhr = new XMLHttpRequest(); //由于上個判斷已經(jīng)將IE無情地拋棄在這個條件分支之外,所以大膽地用 new XMLHttpRequest()吧
xhr.onreadystatechange = callback;
xhr.open("GET",targetUrl);
xhr.send();
}
else{ //最無奈的后招,Cache Trick,新版chromei已經(jīng)不支持
script.onload = callback;
script.type = 'text/cache';
script.src = targetUrl;
}
}else{
if(canContrlExecutionOrderByAsync){ //如果能夠通過script元素的async屬性來強制并行加載的腳本順序執(zhí)行
//kyle大神著力推進的提案,目前已被html5小組接受并放入草案:/Dynamic_Script_Execution_Order#My_Solution
script.onload = callback;
script.async = false; //將script元素的async設(shè)為false,可以保證script的執(zhí)行順序與請求順序保持一致
script.src = targetUrl;
}
else{
script.onload = callback;
script.src = targetUrl;
}
}
實際上,當你在頁面創(chuàng)建一個img節(jié)點,并將其src指向一個腳本文件,在部分瀏覽器里同樣能夠起到文件預加載的作用,那么LABjs的作者是不是沒有想到這一點呢?
- jquery及js實現(xiàn)動態(tài)加載js文件的方法
- 如何實現(xiàn)JavaScript動態(tài)加載CSS和JS文件
- 使用jquery動態(tài)加載Js文件和Css文件
- 使用javaScript動態(tài)加載Js文件和Css文件
- 使用jquery動態(tài)加載js文件的方法
- JS獲取瀏覽器語言動態(tài)加載JS文件示例代碼
- javascript中動態(tài)加載js文件多種解決辦法總結(jié)
- 動態(tài)加載JS文件的三種方法
- 用ajax動態(tài)加載需要的js文件
- 動態(tài)加載js文件 document.createElement
- 動態(tài)加載js文件簡單示例
相關(guān)文章
JS基于FileSaver.js插件實現(xiàn)文件保存功能示例
這篇文章主要介紹了JS基于FileSaver.js插件實現(xiàn)文件保存功能,結(jié)合實例形式演示了FileSaver.js插件的具體使用技巧,需要的朋友可以參考下2016-12-12
解決微信授權(quán)成功后點擊按返回鍵出現(xiàn)空白頁和報錯的問題
這篇文章主要介紹了解決微信授權(quán)成功后點擊按返回鍵出現(xiàn)空白頁和報錯的問題,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-06-06
用js來刷新當前頁面保留參數(shù)的具體實現(xiàn)
本文為大家詳細介紹下如何使用js來刷新當前頁面保留參數(shù),下面有個不錯的實現(xiàn)大家可以看看2013-12-12
JS大坑之19位數(shù)的Number型精度丟失問題詳解
這篇文章主要介紹了JS大坑之19位數(shù)的Number型精度丟失問題,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-04-04
自動刷新網(wǎng)頁,自動刷新當前頁面,JS調(diào)用
自動刷新網(wǎng)頁,自動刷新當前頁面,JS調(diào)用,需要的朋友可以參考一下2013-06-06

