requirejs 讓人迷惑的路徑解析

2021-09-23 21:12:58 字數 4927 閱讀 7645

接觸過requirejs的童鞋可能都知道,無論是通過define來定義模組,還是通過require來載入模組,模組依賴宣告都是很重要的一步。而其中涉及到的模組路徑解析,對於新手來說,有的時候會讓人覺得很困惑。

假設我們的目錄結構如下:

demo.html

js/main.js

js/lib.js

js/util.js

js/common/lib.js

js/common/jqury/lib.js

common/lib.js

下面的這兩個例子,看著很簡單吧,但應該大部分的人跟我一樣沒辦法一眼就識別出來依賴模組最終轉化成的路徑。原因在於,這裡壓根就沒有提供足夠的上下文資訊。。。(= =b 別打我)

require例子:

// main.js

require

(['./util'

], function

());

define例子:

define(['./util'

], function

());

下面,我們再一步步通過具體的例子來看下,requirejs在不同的場景下,是如何解析模組路徑的。

在requirejs的模組路徑解析裡,baseurl是非常基礎的概念,離開了它,基本就玩不轉了,所以這裡簡單介紹一下。簡單的說,baseurl指定了乙個目錄,然後requirejs基於這個目錄來尋找依賴的模組。

舉個栗子,在demo.html裡載入requirejs,同時在requirejs所在的script上宣告data-main屬性,那麼,requirejs載入下來後,它會做兩件事件:

載入js/main.js

將baseurl設定為data-main指定的檔案所在的路徑,這裡是 js/

<

script

src=

"js/require.js"

data-main

="js/main.js"

>

script

>

那麼,下面依賴的lib模組的實際路徑為js/lib.js

main.js

require

(['lib'

], function

(lib)

);

當然,除了data-main屬性,你也可以手動配置baseurl,比如下面例子。需要強調的是:

如果沒有通過data-main屬性指定baseurl,也沒有通過config的方式顯示宣告baseurl,那麼baseurl預設為載入requirejs的那個頁面所在的路徑

demo.html

<

script

src=

"js/require.js"

>

script

>

<

script

src=

"js/main.js"

>

script

>

main.js

requirejs.config();

require

(['lib'

], function

(lib)

);

比如我們載入了下面一堆模組(好多水果。。。),看著下面一長串的依賴列表,可能你一下子就看出問題來了:

費力氣:每個載入的模組前面都有長長的common/fruits難維護:說不定哪一天目錄名就變了(在大型專案中並不算罕見),想象一下目錄結構變更帶來的工作量

requirejs.config();

// 載入一堆水果

require

, 'common/fruits/orange'

, 'common/fruits/grape'

, 'common/fruits/pears'

], function

);

對乙個模組載入器來說,上面說的這兩點問題顯然需要考慮進去。於是requirejs的作者提供了paths這個配置項。我們看下修改後的**。

requirejs.config(

});// 載入一堆水果

require

, 'fruits/orange'

, 'fruits/grape'

, 'fruits/pears'

], function

);

其實就少了個common字首,也沒節省多少**,但當專案結構變更時,好處就體現了。假設common/fruits某一天突然變成了common/third-party/fruits,那很簡單,改下paths就可以了。

requirejs

.config

(});

上一節已經舉例說明了path的例子。這裡再來個例子,說明下下三種情況下,匹配路徑的規則

>

requirejs.config(

});// 從左到右,載入的路徑依次為 js/lib.js、 js/common/jquery/lib.js、common/lib.js

require

], function

());

應該說,這個是最讓人疑惑的地方。

js/main.js

requirejs.config();

// 實際載入的路徑都是是 /lib.js

require

(['./lib'

, 'lib'

], function

(lib)

);

簡單改下上面的例子,可以看到:

通過define定義模組a時,模組a依賴的模組b,如果是./module形式,則基於模組a所在目錄解析模組b的路徑。

js/main.js

requirejs.config();

// 依賴lib.js,實際載入的路徑是 js/common/lib.js,而lib模組又依賴於util模組('./util'),解析後的實際路徑為 js/common/util.js

require

(['common/lib'

], function

(lib)

);

js/lib.js

// 依賴util模組

define(['./util'

], function

(util)

};});

demo2實際上會有特例,比如下面,lib模組依賴的util模組,最終解析出來的路徑是js/util.js

main.js

requirejs.config(

});// 實際載入的路徑是 js/common/lib.js

require

(['lib'

], function

(lib)

);

lib.js

// util模組解析後的路徑為 js/util.js

define(['./util'

], function

(lib)

};});

上面講到通過paths指定的模組路徑載入模組時,./module路徑解析就會按照baseurl+modulename的方式,但稍微修改下main.js,發現結果就不一樣了。此時,util模組對應的路徑為js/common/util.js

main.js

requirejs.config(

});// 實際載入的路徑是 js/common/lib.js

require

(['common/lib'

], function

(lib)

);

util.js

define(['./util'

], function

(lib)

};});

如下面例子所示,我們可能會疑惑,為什麼不是相對於main.js所在的路徑解析呢?其實很簡單,作者也不知道你這段**出現在哪個檔案呀親。所以,只能通過baseurl

js/main.js

require

(['./lib'

, function

(lib)

]);

加個@todo,這個估計只有作者和看過原始碼的人知道了,好像文件裡也沒明確說到~todo下先

// @todo

囉囉嗦嗦寫了一大堆,requirejs中的路徑解析整體上不複雜,但./module這種形式的路徑解析,對於剛接觸requirejs的人來說稍微有些費解。也許,當你從requirejs設計者的角度來看,問題可能相對好理解一些。

requirejs 讓人迷惑的路徑解析

接觸過requirejs的童鞋可能都知道,無論是通過define來定義模組,還是通過require來載入模組,模組依賴宣告都是很重要的一步。而其中涉及到的模組路徑解析,對於新手來說,有的時候會讓人覺得很困惑。假設我們的目錄結構如下 demo.html js main.js js lib.js js ...

讓人迷惑的命名

讓人迷惑的命名 jdk1.5中的string的兩個方法replace和replaceall。從名字你絕對猜不到replaceall的真正用途。string replace char oldchar,char newchar 返回乙個新的字串,它是通過用newchar替換此字串中出現的所有oldcha...

那些年讓人迷惑的同步 非同步 阻塞 非阻塞

這些概念之所以容易令人迷惑,在於很多人對i o就沒有清晰準確的理解,後面的理解自然不可能正確。我想用乙個具體的例子來說明一下i o。設想自己是乙個程序,就叫小進吧。小進需要接收乙個輸入,我們不管這個輸入是從網路套接字來,還是鍵盤,滑鼠來,輸入的 可以千千萬萬。但是,都必須由核心來幫小進完成,為啥核心...