JS異步加載庫LABjs簡易說明

1、關於LABjs的簡單介紹

做者:Kyle Simpsonjavascript

做用:動態並行加載腳本文件 以及 管理加載腳本文件的執行順序php

官網:http://www.labjs.com/html

 

2、關於LABjs的使用

如下實例原文連接:http://www.au92.com/archives/labjs.htmlhtml5

更全更詳細說明:http://labjs.com/documentation.phpjava

實例1:ajax

$LAB.script("script1.js")
    .script("script2.js")
    .script("script3.js")
    .wait(function(){// 等待全部script加載完再執行這個代碼塊        script1Func();
        script2Func();
        script3Func();
    });

實例2:chrome

$LAB.script({ src:"script1.js", type:"text/javascript"})
    .script("script2.js")
    .script("script3.js")
    .wait(function(){// 等待全部script加載完再執行這個代碼塊        script1Func();
        script2Func();
        script3Func();}
    );

實例3:跨域

$LAB.script("script1.js","script2.js","script3.js")
    .wait(function(){// 等待全部script加載完再執行這個代碼塊        script1Func();
        script2Func();
        script3Func();
    });

實例4:瀏覽器

$LAB.script(["script1.js","script2.js"],"script3.js")
    .wait(function(){// 等待全部script加載完再執行這個代碼塊        script1Func();
        script2Func();
        script3Func();
    });

實例5:緩存

$LAB.script("script1.js")
    .wait()    // 空的wait()只是確保script1在其餘代碼以前被執行
    .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 之間沒有依賴關係, 
    .script("script2.js")    // 因此能夠任意順序執行
    .script("script3.js")
    .wait(function(){    // 若是須要,這裏固然能夠執行javascript函數
        alert("Scripts 1-3 are loaded!");
    })
    .script("script4.js")    // 依賴於 script1, script2 及 script3 
    .wait(function(){script4Func();});

實例7:

$LAB.setOptions({AlwaysPreserveOrder:true})// 設置每一個腳本之間等待
    .script("script1.js")// script1, script2, script3, script4 互相依賴
    .script("script2.js")// 而且並行下載後循序執行
    .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();

3、LABjs主要採用加載方式

LABjs裏的動態加載腳本文件,是指頁面的js腳本執行時,經過多種方法去加載外部的js(主要區別於html頁面裏,經過<script>標籤靜態加載的腳本)

動態加載腳本的方式有不少,優缺點不一,此處不贅述,有興趣的童鞋能夠參見本文末尾的參考連接 :)。

LABjs裏主要使用了三種技巧,分別爲Script ElementXHR Injection以及Cache Trick

首先對這三種加載方式進行簡單介紹,第四部分再分析LABjs源碼實現裏面對着三種方式分別的使用場景

 

Script Element(LABjs默認採用加載方式) 

最多見的腳本動態加載方式,優勢不少,包括:一、實現簡單 二、可跨域 三、不會阻塞其餘資源的加載 等

Opera/Firefox(老版本)下:腳本執行的順序與節點被插入頁面的順序一致

IE/Safari/Chrome下:執行順序沒法獲得保證

注意:

  • 新版本的Firefox下,腳本執行的順序與插入頁面的順序不必定一致,但可經過將script標籤的async屬性設置爲false來保證順序執行

  • 老版本的Chrome下,腳本執行的順序與插入頁面的順序不必定一致,但可經過將script標籤的async屬性設置爲false來保證順序執行

 

XHR Injection

經過ajax請求加載腳本文件,而後再經過如下方式執行:

  • eval:常見方式

  • XHR injection:建立一個script元素,並將請加載的腳本文件的內容注入

主要限制:沒法跨域

 

Cache Trick(強依賴於瀏覽器的特性實現,不推薦使用)

當你將script元素的type屬性設置爲瀏覽器不認識的值,好比"text/cache"、"text/casper"、"text/hellworld"等,不一樣瀏覽器的行爲以下:

IE/Safari/Chrome(老版本)裏:腳本照常加載,但不會執行,假設瀏覽器沒有禁用緩存,加載後的腳本會被瀏覽器緩存起來,當須要用到的時候,只須要從新建立個script標籤,將type設爲正確的值,src指向以前請求的文件url便可(至關於從緩存裏讀文件)

Opera/Firefox:不加載

備註:

  • 強依賴於瀏覽器的特性實現,有可能隨着瀏覽器特性實現的改變而失效,不推薦使用

  • 新版本的chrome瀏覽器,將script元素的type設置爲非"text/javascript",不會再對腳本文件進行加載

 

4、LABjs裏關於腳本加載採用方案的判斷

忽略技術細節,經過一段僞代碼來描述LABjs裏面的實現,大體爲:

首先判斷是否對請求的腳本進行預加載(是否進行預加載的判斷條件看僞代碼註釋);

如進行預加載,再判斷瀏覽器是否支持真正的預加載;如支持真正的預加載,則預加載之;如否,判斷請求的腳本是否跟當前頁面同域,如實,採用XHR Injection,如否,採用Cache Trick;

如不進行預加載,判斷瀏覽器支不支持script元素的async屬性(見僞代碼註釋),如是,設置async屬性,並請求腳本文件;如否,直接經過script元素加載腳本文件;

if(ifPreloadScript){    //當請求的腳本文件是否進行預加載:一、須要預加載 二、瀏覽器支持預加載

    if(supportRealPreloading){    //若是支持真正的預加載

        if(supportPreloadPropNatively){    //支持經過設置script標籤的preload屬性,實現script的預加載,以及分離加載和執行
                                        //Nicholas C. Zakas大神的美好願望,還沒有有瀏覽器支持:http://www.nczonline.net/blog/2011/02/14/separating-javascript-download-and-execution/
            script.onpreload = callback;
            script.newPreload = true;
            script.src = targetUrl;

        }else{

            script.onreadystatechange = callback;    //其實就是指IE瀏覽器,假設指定了script元素的src屬性,IE瀏覽器裏會當即加載
            script.src = targetUrl;    //即便script元素沒有被插入頁面,callback爲預加載後的回調        }

    }    else if(inSameDomain){    //非跨域,採用XHR Injection:請求的腳本與當前頁面處於同一個域
        xhr = new XMLHttpRequest();    //因爲上個判斷已經將IE無情地拋棄在這個條件分支以外,因此大膽地用 new XMLHttpRequest()吧
        xhr.onreadystatechange = callback;
        xhr.open("GET",targetUrl);
        xhr.send();

    }    else{    //最無奈的後招,Cache Trick,新版chromei已經不支持
        script.onload = callback;
        script.type = 'text/cache';    
        script.src = targetUrl;
    }

}else{    if(canContrlExecutionOrderByAsync){    //若是可以經過script元素的async屬性來強制並行加載的腳本順序執行
                                        //kyle大神着力推動的提案,目前已被html5小組接受並放入草案:http://wiki.whatwg.org/wiki/Dynamic_Script_Execution_Order#My_Solution
        script.onload = callback;
        script.async = false;    //將script元素的async設爲false,能夠保證script的執行順序與請求順序保持一致
        script.src = targetUrl;

    }    else{

        script.onload = callback;
        script.src = targetUrl;    
    }
}

實際上,當你在頁面建立一個img節點,並將其src指向一個腳本文件,在部分瀏覽器裏一樣可以起到文件預加載的做用,那麼LABjs的做者是否是沒有想到這一點呢?

很多LABjs的使用者都向kyle提過上面這個問題,key表示:在現有加載策略已經可以知足需求的狀況下,不想讓LABjs的設計變得更復雜了(非原話)

 

寫在後面

此處僅僅簡單對LABjs的做用、用法以及內部實現簡單介紹了下,關於內部具體源代碼實現的分析,留待下一篇文章

若有錯漏,請指出 ,若有問題,歡迎回復以及郵件進一步交流 :)

相關文章
相關標籤/搜索