理解包結(jié)構(gòu)
commonjs包結(jié)構(gòu)規(guī)范:http://wiki.commonjs.org/wiki/Packages/1.0
- 一個(gè)package.json文件應(yīng)該存在于包頂級(jí)目錄下
- 二進(jìn)制文件應(yīng)該包含在bin目錄下南吮。
- JavaScript代碼應(yīng)該包含在lib目錄下义钉。
- 文檔應(yīng)該在doc目錄下环形。
- 單元測(cè)試應(yīng)該在test目錄下。
理解描述文件package.json
輸入 npm init
后會(huì)彈出一堆問題,我們可以輸入對(duì)應(yīng)內(nèi)容,也可以使用默認(rèn)值。在回答一堆問題后輸入 yes
就會(huì)生成圖中所示內(nèi)容的 package.json
文件鸠天。如果嫌回答這一大堆問題麻煩,可以直接輸入 npm init --yes
跳過回答問題步驟帐姻,直接生成默認(rèn)值的 package.json
文件
- name稠集。包名,需要在NPM上是唯一的卖宠,不能帶有空格巍杈。
- description忧饭。包簡(jiǎn)介扛伍,通常會(huì)顯示在一些列表中。
- version词裤。版本號(hào)刺洒,一個(gè)語(yǔ)義化的版本號(hào)(http://semver.org/ ),通常為x.y.z吼砂。
- keywords逆航。關(guān)鍵字?jǐn)?shù)組,用于NPM中的分類搜索渔肩。
- maintainers因俐。包維護(hù)者的數(shù)組,數(shù)組元素是一個(gè)包含name周偎、email抹剩、web三個(gè)屬性的JSON對(duì)象。
- contributors蓉坎。包貢獻(xiàn)者的數(shù)組澳眷。第一個(gè)就是包的作者本人。在開源社區(qū)蛉艾,如果提交的patch被merge進(jìn)master分支的話钳踊,就應(yīng)當(dāng)加上這個(gè)貢獻(xiàn)patch的人。格式包含name和email勿侯。
"contributors": [{
"name": "Jackson Tian",
"email": "mail @gmail.com"
}, {
"name": "fengmk2",
"email": "mail2@gmail.com"
}],
bugs拓瞪。一個(gè)可以提交bug的URL地址,可以是郵件地址(mailto:mailxx@domain)助琐,也可以是網(wǎng)頁(yè)地址(http://url)祭埂。
licenses。包所使用的許可證弓柱,例如:
"licenses": [{ "type": "GPLv2", "url": "http://www.example.com/licenses/gpl.html", }]
repositories沟堡。托管源代碼的地址數(shù)組侧但。
dependencies。當(dāng)前包需要的依賴航罗,這個(gè)屬性十分重要禀横,NPM會(huì)通過這個(gè)屬性,幫你自動(dòng)加載依賴的包粥血。
理解npm install
我們可以把項(xiàng)目發(fā)布到npm中央倉(cāng)庫(kù)柏锄,別人拿到我們的項(xiàng)目時(shí),可以執(zhí)行npm install下載所需要的模塊复亏,這些模塊是依賴package.json中定義的趾娃,這些依賴都會(huì)被安裝在當(dāng)前目錄下。
npm的包安裝分為本地安裝(local)缔御、全局安裝(global)兩種抬闷。
npm install xxx # 本地安裝
將安裝包放在 ./node_modules 下(運(yùn)行npm時(shí)所在的目錄)
npm install -g xxx # 全局安裝
將安裝包放在/usr/local/lib/node_modules下。
使用 npm install
時(shí)增加 --save
或者 --save -dev
表示將這個(gè)包名及對(duì)應(yīng)的版本添加到 package.json
的 dependencies
或devDependencies
耕突。
使用模塊
使用require函數(shù)用于在當(dāng)前模塊中加載和使用別的模塊笤成,傳入一個(gè)模塊名,返回一個(gè)模塊導(dǎo)出對(duì)象眷茁。
優(yōu)先從緩存中加載模塊炕泳,其次在核心模塊中加載,然后是指定文件路徑的模塊加載上祈,如果以上三個(gè)條件均不滿足培遵,則定義為自定義模塊,查找策略為從當(dāng)前目錄下的node_modules查找登刺,找不到則向父目錄的node_modules查找籽腕,直到根目錄或找到為止。
如果在環(huán)境變量中設(shè)置了HOME目錄和NODE_PATH目錄的話塘砸,整個(gè)路徑還包含NODE_PATH和HOME目錄下的.node_libraries與.node_modules节仿。
全局模塊
為什么我們使用npm install -g命令安裝的模塊不能即時(shí)生效,那是因?yàn)閚pm install -g 會(huì)將模塊默認(rèn)安裝在/usr/local/lib/node_modules中掉蔬,而require模塊的流程如剛才所說廊宪,默認(rèn)情況下并沒有自動(dòng)查找到全局路徑中。
可以通過三種方法解決:
- 可以在工程目錄下執(zhí)行npm link module_name
- 可以設(shè)置環(huán)境變量NODE_PATH
- 可以軟鏈接一個(gè)目錄女轿,在某個(gè)父節(jié)點(diǎn)路徑中創(chuàng)建node_modules箭启,如下:
設(shè)置一個(gè)代理全局模塊路徑,這樣npm install -g的模塊都會(huì)安裝在此
npm config set prefix "~/npm_global"
建立一個(gè)軟鏈接
ln -s ~/npm_global/lib/node_modules ~/node_modules
查看全局安裝模塊的命令:
npm list --depth=0 -global
導(dǎo)出模塊
exports該對(duì)象是當(dāng)前模塊的導(dǎo)出對(duì)象蛉迹,用于導(dǎo)出模塊公有方法和屬性傅寡,默認(rèn)為一個(gè)空對(duì)象{}。別的模塊通過require()函數(shù)使用當(dāng)前模塊時(shí)得到的就是當(dāng)前模塊的exports對(duì)象。以下代碼中導(dǎo)出了一個(gè)公有方法:
exports.hello = function() {
console.log("Hello World!");
};
在下面的情況下荐操,你的模塊是一個(gè)類:
module.exports = function(name, age) {
this.name = name;
this.age = age;
this.about = function() {
console.log(this.name +' is '+ this.age +' years old');
};
};
然后你應(yīng)該這樣使用它:
var Rocker = require('./rocker.js');
var r = new Rocker('Ozzy', 62);
r.about(); // Ozzy is 62 years old
在下面的情況下芜抒,你的模塊是一個(gè)數(shù)組:
module.exports = ['Lemmy Kilmister', 'Ozzy Osbourne', 'Ronnie James Dio', 'Steven Tyler', 'Mick Jagger'];
然后你應(yīng)該這樣使用它:
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
當(dāng)前沒有任何屬性的話屯耸,exports
會(huì)把這些屬性賦予module.exports
拐迁。如果module.exports
已經(jīng)存在一些屬性的話,那么exports
中所用的東西都會(huì)被忽略疗绣。
簡(jiǎn)單理解核心模塊
核心模塊中线召,有些模塊使用C/C++編寫,有些則由C/C++完成核心部分多矮,由JavaScript實(shí)現(xiàn)包裝和向外導(dǎo)出缓淹。
內(nèi)建模塊被統(tǒng)一放在一個(gè)node_module_list數(shù)組中,通過get_builtin_module方法取出工窍,通過執(zhí)行register_func()填充exports對(duì)象割卖,將exports對(duì)象緩存并返回給調(diào)用方前酿。