理解包結(jié)構(gòu)
commonjs包結(jié)構(gòu)規(guī)范:http://wiki.commonjs.org/wiki/Packages/1.0
- 一個package.json文件應該存在于包頂級目錄下
- 二進制文件應該包含在bin目錄下。
- JavaScript代碼應該包含在lib目錄下。
- 文檔應該在doc目錄下。
- 單元測試應該在test目錄下。
理解描述文件package.json
輸入 npm init 后會彈出一堆問題,我們可以輸入對應內(nèi)容,也可以使用默認值。在回答一堆問題后輸入 yes 就會生成圖中所示內(nèi)容的 package.json 文件。如果嫌回答這一大堆問題麻煩,可以直接輸入 npm init --yes 跳過回答問題步驟,直接生成默認值的 package.json 文件
- name。包名,需要在NPM上是唯一的,不能帶有空格。
- description。包簡介,通常會顯示在一些列表中。
- version。版本號,一個語義化的版本號(http://semver.org/ ),通常為x.y.z。
- keywords。關(guān)鍵字數(shù)組,用于NPM中的分類搜索。
- maintainers。包維護者的數(shù)組,數(shù)組元素是一個包含name、email、web三個屬性的JSON對象。
- contributors。包貢獻者的數(shù)組。第一個就是包的作者本人。在開源社區(qū),如果提交的patch被merge進master分支的話,就應當加上這個貢獻patch的人。格式包含name和email。
"contributors": [{
"name": "Jackson Tian",
"email": "mail @gmail.com"
}, {
"name": "fengmk2",
"email": "mail2@gmail.com"
}],
bugs。一個可以提交bug的URL地址,可以是郵件地址(mailto:mailxx@domain),也可以是網(wǎng)頁地址(http://url)。
licenses。包所使用的許可證,例如:
"licenses": [{ "type": "GPLv2", "url": "http://www.example.com/licenses/gpl.html", }]repositories。托管源代碼的地址數(shù)組。
dependencies。當前包需要的依賴,這個屬性十分重要,NPM會通過這個屬性,幫你自動加載依賴的包。
理解npm install
我們可以把項目發(fā)布到npm中央倉庫,別人拿到我們的項目時,可以執(zhí)行npm install下載所需要的模塊,這些模塊是依賴package.json中定義的,這些依賴都會被安裝在當前目錄下。
npm的包安裝分為本地安裝(local)、全局安裝(global)兩種。
npm install xxx # 本地安裝
將安裝包放在 ./node_modules 下(運行npm時所在的目錄)
npm install -g xxx # 全局安裝
將安裝包放在/usr/local/lib/node_modules下。
使用 npm install 時增加 --save 或者 --save -dev 表示將這個包名及對應的版本添加到 package.json的 dependencies或devDependencies。
使用模塊
使用require函數(shù)用于在當前模塊中加載和使用別的模塊,傳入一個模塊名,返回一個模塊導出對象。
優(yōu)先從緩存中加載模塊,其次在核心模塊中加載,然后是指定文件路徑的模塊加載,如果以上三個條件均不滿足,則定義為自定義模塊,查找策略為從當前目錄下的node_modules查找,找不到則向父目錄的node_modules查找,直到根目錄或找到為止。
如果在環(huán)境變量中設置了HOME目錄和NODE_PATH目錄的話,整個路徑還包含NODE_PATH和HOME目錄下的.node_libraries與.node_modules。
全局模塊
為什么我們使用npm install -g命令安裝的模塊不能即時生效,那是因為npm install -g 會將模塊默認安裝在/usr/local/lib/node_modules中,而require模塊的流程如剛才所說,默認情況下并沒有自動查找到全局路徑中。
可以通過三種方法解決:
- 可以在工程目錄下執(zhí)行npm link module_name
- 可以設置環(huán)境變量NODE_PATH
- 可以軟鏈接一個目錄,在某個父節(jié)點路徑中創(chuàng)建node_modules,如下:
設置一個代理全局模塊路徑,這樣npm install -g的模塊都會安裝在此
npm config set prefix "~/npm_global"
建立一個軟鏈接
ln -s ~/npm_global/lib/node_modules ~/node_modules
查看全局安裝模塊的命令:
npm list --depth=0 -global
導出模塊
exports該對象是當前模塊的導出對象,用于導出模塊公有方法和屬性,默認為一個空對象{}。別的模塊通過require()函數(shù)使用當前模塊時得到的就是當前模塊的exports對象。以下代碼中導出了一個公有方法:
exports.hello = function() {
console.log("Hello World!");
};
在下面的情況下,你的模塊是一個類:
module.exports = function(name, age) {
this.name = name;
this.age = age;
this.about = function() {
console.log(this.name +' is '+ this.age +' years old');
};
};
然后你應該這樣使用它:
var Rocker = require('./rocker.js');
var r = new Rocker('Ozzy', 62);
r.about(); // Ozzy is 62 years old
在下面的情況下,你的模塊是一個數(shù)組:
module.exports = ['Lemmy Kilmister', 'Ozzy Osbourne', 'Ronnie James Dio', 'Steven Tyler', 'Mick Jagger'];
然后你應該這樣使用它:
var rocker = require('./rocker.js');
console.log('Rockin in heaven: ' + rocker[2]); //Rockin in heaven: Ronnie James Dio
exports只是module.exports的輔助方法。你的模塊最終返回module.exports給調(diào)用者,而不是exports。exports所做的事情是收集屬性,如果module.exports當前沒有任何屬性的話,exports會把這些屬性賦予module.exports。如果module.exports已經(jīng)存在一些屬性的話,那么exports中所用的東西都會被忽略。
簡單理解核心模塊
核心模塊中,有些模塊使用C/C++編寫,有些則由C/C++完成核心部分,由JavaScript實現(xiàn)包裝和向外導出。
內(nèi)建模塊被統(tǒng)一放在一個node_module_list數(shù)組中,通過get_builtin_module方法取出,通過執(zhí)行register_func()填充exports對象,將exports對象緩存并返回給調(diào)用方。