這兩天正好看到了程式員小卡同學的一篇部落格,裡面對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,如需轉載請自行聯系原作者