- http、fs、path等,原生模塊
- ./mod或../mod,相對路徑的文件模塊
- /pathtomodule/mod,絕對路徑的文件模塊
- mod,非原生模塊的文件模塊
在進入路徑查找以前有必要描述一下module path這個Node.js中的概念。對於每個被加載的文件模塊,建立這個模塊對象的時候,這個模塊便會有一個paths屬性,其值根據當前文件的路徑計算獲得。Node.js在編譯js文件的過程當中實際完成的步驟有對js文件內容進行頭尾包裝。以app.js爲例,咱們將其放在任意一個文件夾中,包裝以後的app.js將會變成如下形式:javascript
在app.js中輸入以下內容:java
執行node module app.js命令,將獲得如下的輸出結果:node
Windows下:npm
能夠看出module path的生成規則爲:從當前文件目錄開始查找node_modules目錄;而後依次進入父目錄,查找父目錄下的node_modules目錄;依次迭代,直到根目錄下的node_modules目錄。json
除此以外還有一個全局module path,是當前node執行文件的相對目錄(../../lib/node)。若是在環境變量中設置了HOME目錄和NODE_PATH目錄的話,整個路徑還包含NODE_PATH和HOME目錄下的.node_libraries與.node_modules。其最終值大體以下:數組
一、從module path數組中取出第一個目錄做爲查找基準。 緩存
二、直接從目錄中查找該文件,若是存在,則結束查找。若是不存在,則進行下一條查找。 app
三、嘗試添加.js、.json、.node後綴後查找,若是存在文件,則結束查找。若是不存在,則進行下一條。ui
四、嘗試將require的參數做爲一個包來進行查找,讀取目錄下的package.json文件,取得main參數指定的文件。 spa
五、嘗試查找該文件,若是存在,則結束查找。若是不存在,則進行第3條查找。
六、若是繼續失敗,則取出module path數組中的下一個目錄做爲基準查找,循環第1至5個步驟。
七、若是繼續失敗,循環第1至6個步驟,直到module path中的最後一個值。
八、若是仍然失敗,則拋出異常。
因爲 Node.js 中存在 4 類模塊(原生模塊和3種文件模塊),儘管 require 方法極其簡單,可是內部的加載倒是十分複雜的,其加載優先級也各自不一樣。以下圖所示:
1、優先從文件模塊緩存中加載
儘管原生模塊與文件模塊的優先級不一樣,可是都會優先從文件模塊的緩存中加載已經存在的模塊。
2、原生模塊
原生模塊的優先級僅次於文件模塊緩存的優先級。require 方法在解析文件名以後,優先檢查模塊是否在原生模塊列表中。
在實際開發過程當中,若是你的文件和核心庫文件同名,加載過程當中是會直接忽略你的項目文件。
例如在server下有config.json,require("config")。
require具體的加載過程是:
(1)核心庫中若是有config.js 會直接加載 忽略你的文件。
(2)若是沒有會檢查你的項目中是否有這個.js文件。
(3)若是沒有才會去查詢 .json 文件。
因此在開發過程當中最好使用其相對路徑指明具體文件。
當第三方的模塊和內置模塊同名時,內置模塊將覆蓋第三方同名模塊。所以命名時須要注意不要和內置模塊同名。
原生模塊也有一個緩存區,一樣也是優先從緩存區加載。若是緩存區沒有被加載過,則調用原生模塊的加載方式進行加載和執行。
原生模塊的本質也是文件,原生模塊文件已經被編譯到了二進制文件中了,咱們只須要按照名字來加載就能夠了。如:
一、require(‘fs’)
二、require(‘http’)
3、路徑形式的模塊
咱們說的路徑形式的模塊,其實就是加載本身寫的JS文件,有四種方式能夠加載
當文件模塊緩存中不存在,並且不是原生模塊的時候,Node.js 會解析 require 方法傳入的參數,並從文件系統中加載實際的文件 。
注意,這裏忽略了擴展名「.js」,如下是對等的:
若是當前目錄有my_mod.js和my_mod.json,則會優先加載 my_mod.js。
能夠直接require一個目錄,假設有一個目錄名爲folder,如:
此時,Node將搜索整個folder目錄,Node會假設folder爲一個包並試圖找到包定義文件package.json。若是folder 目錄裏沒有包含package.json文件,Node會假設默認主文件爲index.js,即會加載index.js。若是index.js也不存在, 那麼加載將失敗。
假如目錄結構以下:
package.json定義以下:
此時 require('./folder') 將返回模塊modA.js。若是package.json不存在,那麼將返回模塊index.js。若是index.js也不存在,那麼將發生載入異常。
若是foder同級目錄還有folder.js和folder.json,同時folder目錄下還有index.js,則require('./folder') 將返回folder.js中的內容,不然返回folder.json中的內容,不然會返回folder目錄下index.js中的內容,最後纔會返回modA.js中的內容。
4、第三方模塊
凡是用到第三方模塊,都必須經過 npm 來下載;
使用的時候就能夠經過 require(‘包名’) 的方式來進行加載纔可使用;
不可能有任何一個第三方包和核心模塊的名字是同樣的。
既不是核心模塊、也不是路徑形式的模塊,就是第三方模塊。
若是模塊名不是路徑,也不是內置模塊,Node將試圖去當前目錄的node_modules文件夾裏搜索。若是當前目錄的node_modules裏沒有找到,Node會從父目錄的node_modules裏搜索,這樣遞歸下去直到根目錄。
總結:
其實主要就是兩種狀況:
一、若是require中是名稱,則說明搜索的是內置模塊或者第三方模塊,此時內置模塊的優先級高於第三方模塊;
二、若是require中是路徑,則會按照自定義模塊的規則查找。