天天看點

【requireJS路徑加載】與程式員小卡的交流

這兩天正好看到了程式員小卡同學的一篇部落格,裡面對requireJS路徑的解析做了一些說明,裡面有點問題待解決,我這裡正好知道一點,是以整理成文,不知對小卡同學是否有幫助。

http://www.cnblogs.com/chyingp/p/3677425.html

http://www.cnblogs.com/chyingp/p/requirejs-path-resolve.html

首先以其例子為例:

複制代碼

requirejs.config({

    baseUrl: 'js'

});

// 依賴lib.js,實際加載的路徑是 js/common/lib.js,而lib子產品又依賴于util子產品('./util'),解析後的實際路徑為 js/common/util.js

require(['common/lib'], function(Lib){

    Lib.say('hello');

// 依賴util子產品

define(['./util'], function(Util){

    return {

        say: function(msg){

            Util.say(msg);

        }

    };

若是變個寫法,util的目錄結構就變了

    baseUrl: 'js',

    paths: {

        lib: 'common/lib'

    }

// 實際加載的路徑是 js/common/lib.js

require(['lib'], function(Lib){

// util子產品解析後的路徑為 js/util.js

define(['./util'], function(Lib){

            Lib.say(msg);

我們今天便一起來學習下這個問題

requireJS的basePath

對于baseUrl的解析需要注意,當滿足以下條件,将不會相對baseUrl

① 以"/"開頭

② 以".js"結尾

③ 包含各種協定

不出現以上條件,設定的path,是相對于baseUrl的

簡單requireJS流程

然後我們這裡再簡單的整理下requireJS這部分的流程:

① 通過require加載主幹流程,這裡就是我們所謂的入口,以上述代碼為例,入口是:

該代碼會在require内部執行過程中,具有第一個依賴項,這個依賴項是'common/lib',他的鍵值便是這個了

這裡會首先加載器依賴項,common/lib,而此時便會做第一步的解析并且形成一個子產品

在子產品加載時,會建立一個script标簽,并且為其綁定load事件,這裡會有第二個事件的觸發

② 在加載common/lib子產品時,有一個關鍵點需要注意:

檔案加載結束便會馬上執行,是以其define方法執行了,并且往globalDefQueue寫入了資料

load事件觸發,會建立一個requireJS module,這個時候其依賴項會加載

上述雖然與本次讨論的東西無關,卻是了解整個require的關鍵,各位可以去看看

③ context.completeLoad(data.id) =>但是這個時候卻發現其有一個依賴項,于是便會先加載器依賴項,這裡又會進入,main.js中require的邏輯,即這段代碼:

 1 //Enable each dependency

 2 each(this.depMaps, bind(this, function (depMap, i) {

 3   var id, mod, handler;

 4   if (typeof depMap === 'string') {

 5     //Dependency needs to be converted to a depMap

 6     //and wired up to this module.

 7     depMap = makeModuleMap(depMap,

 8                                   (this.map.isDefine ? this.map : this.map.parentMap),

 9                                   false,

10                                   !this.skipMap);

11     this.depMaps[i] = depMap;

12     handler = getOwn(handlers, depMap.id);

13     if (handler) {

14       this.depExports[i] = handler(this);

15       return;

16     }

17     this.depCount += 1;

18 on(depMap, 'defined', bind(this, function (depExports) {

19   this.defineDep(i, depExports);

20   this.check();

21 }));

22     if (this.errback) {

23       on(depMap, 'error', bind(this, this.errback));

24     }

25   }

26   id = depMap.id;

27   mod = registry[id];

28   //Skip special modules like 'require', 'exports', 'module'

29   //Also, don't call enable if it is already enabled,

30   //important in circular dependency cases.

31   if (!hasProp(handlers, id) && mod && !mod.enabled) {

32     context.enable(depMap, this);

33   }

34 }));

這是非常關鍵的一段代碼,無論裡面的depcount還是其中的on defined事件點注冊皆十分關鍵

從這裡開始會加載util相關資源,于是util進入了相關加載流程了,這也是小卡關注的地方

但是這裡有一個不一樣的地方是,util子產品時具有parentModuleMap的,而common/lib不具有

這裡util與lib有一個映射關系lib->util,是以util的parentName就是common/lib

這個時候就到了解析URL這個步驟了

//name=>./util; parentName=>common/lib

normalizedName = normalize(name, parentName, applyMap);

我們要做的事情就是解析這個位址

 核心代碼

PS:我看requireJS版本,又老了,他的代碼又有更新啊!!!

上面這段代碼是一個關鍵

首先他會将common/lib的目錄解析出來,這裡是common('one/two/three.js', but we want the directory, 'one/two' )

我們這裡首次就直接傳回了,這裡傳回的是common/util

若是我們換一個寫法,會同樣執行上面邏輯,最後卻有所不同,因為這個時候parent的common不見了!

這個時候便會執行傳回util字元串,是以這裡兩個位址便會有所不同:

main.js=>require(['common/lib'], function (Lib)=>common/util

main.js=>require(['lib'], function (Lib)=>util

main.js=>require(['a/b/c/lib'], function (Lib)=>a/b/c/util

這裡util是相對于父級的目錄,這個是其位址變化的主要原因

是以,現在關于小卡的問題應該得到了解決,至于其map映射關系是如何形成的,這個話題就更加深了

小钗requireJS也是初學,很多不懂,不知是不是解決了小卡的問題,這裡提出來各位高手一起看看,有誤請提出。

本文轉自葉小钗部落格園部落格,原文連結http://www.cnblogs.com/yexiaochai/p/3768570.html,如需轉載請自行聯系原作者

繼續閱讀