模塊規(guī)范
Nodejs 對(duì) CommonJS進(jìn)行支持和實(shí)現(xiàn),讓我們?cè)陂_發(fā)Node的過程中科院方便的進(jìn)行模塊化開發(fā)
- 在
Node中每一個(gè)js文件都是一個(gè)單獨(dú)的模塊 - 模塊中包括
CommonJs規(guī)范的核心變量:exports,module.exports,require - 通過上述變量進(jìn)行模塊化開發(fā)
而模塊化的核心是導(dǎo)出與導(dǎo)入,在Node中通過exports與module.exports負(fù)責(zé)對(duì)模塊中的內(nèi)容進(jìn)行導(dǎo)出,通過require函數(shù)導(dǎo)入其他模塊(自定義模塊,系統(tǒng)模塊,第三方模塊)中的內(nèi)容
查找策略
require 方法接收以下幾種參數(shù)的傳遞:
- 原生模塊: http,fs,path等
- 相對(duì)路徑文件模塊:./mod或../mod
- 絕對(duì)路徑的文件模塊: /pathtomodule/mod
- 目錄作為模塊: ./dirname
- 非原生模塊的文件模塊: mod
require參數(shù)較為簡(jiǎn)單,但是內(nèi)部的加載卻十分復(fù)雜,其加載優(yōu)先級(jí)也各自不同
從上圖可以看見,文件模塊存在緩存區(qū),尋找模塊路徑的時(shí)候都會(huì)優(yōu)先從緩存中加載已經(jīng)存在的模塊
原生模塊
如果require絕對(duì)路徑的文件,則直接查找對(duì)應(yīng)的路徑,速度最快
相對(duì)路徑的模塊則相對(duì)于當(dāng)前調(diào)用require的文件去查找
如果按確切的文件名沒有找到模塊,則Nodejs會(huì)嘗試帶上.js,.json或.node擴(kuò)展名再加載
目錄作為模塊
默認(rèn)情況是根據(jù)目錄中的pakage.json文件的main來指定目錄模塊,如:
{
"name":"some-library",
"main":"main.js"
}
如果這是在./some-library node_modules目錄中,則 require('./some-library') 會(huì)試圖加載 ./some-library/main.js
如果目錄里沒有 package.json文件,或者 main入口不存在或無法解析,則會(huì)試圖加載目錄下的 index.js 或 index.node 文件
非原生模塊
在每個(gè)文件中都存在module.paths,表示模塊的搜索路徑,require就是根據(jù)其來尋找文件
在window下輸出如下:
[ 'c:\\nodejs\\node_modules',
'c:\\node_modules' ]
可以看出module path的生成規(guī)則為:從當(dāng)前文件目錄開始查找node_modules目錄;然后依次進(jìn)入父目錄,查找父目錄下的node_modules目錄,依次迭代,直到根目錄下的node_modules目錄
當(dāng)都找不到的時(shí)候,則會(huì)從系統(tǒng)NODE_PATH環(huán)境變量查找
舉個(gè)例子:
如果在/home/ry/projects/foo.js文件里調(diào)用了 require('bar.js'),則 Node.js 會(huì)按以下順序查找:
- /home/ry/projects/node_modules/bar.js
- /home/ry/node_modules/bar.js
- /home/node_modules/bar.js
- /node_modules/bar.js
這使得程序本地化它們的依賴,避免它們產(chǎn)生沖突
總結(jié)
通過上面模塊的文件查找策略之后,總結(jié)下文件查找的優(yōu)先級(jí):
緩存的模塊優(yōu)先級(jí)最高
如果是內(nèi)置模塊,則直接返回,優(yōu)先級(jí)僅次緩存的模塊
如果是絕對(duì)路徑 / 開頭,則從根目錄找
如果是相對(duì)路徑 ./開頭,則從當(dāng)前require文件相對(duì)位置找
如果文件沒有攜帶后綴,先從js、json、node按順序查找
如果是目錄,則根據(jù) package.json的main屬性值決定目錄下入口文件,默認(rèn)情況為 index.js
如果文件為第三方模塊,則會(huì)引入 node_modules 文件,如果不在當(dāng)前倉庫文件中,則自動(dòng)從上級(jí)遞歸查找,直到根目錄
