源連接node
咱們知道的require
函數支持的兩種路徑有:git
/
或者C:
開頭的絕對路徑./
開頭的相對路徑。以上路徑的缺點是:使得模塊之間創建了強耦合關係,一旦某個模塊文件的存放位置須要變動,使用該模塊的其它模塊的代碼也須要跟着調整,變得牽一髮動全身。github
下面來了解一下require
支持的第三種形式的路徑,寫法相似於foo/bar
,按照一下規則解析,直到找到模塊位置。npm
node_modules
目錄是NodeJs定義的用於存放模塊的。當require('foo/bar')時,NodeJs依次嘗試一下路徑: /home/user/node_modules/foo/bar /home/node_modules/foo/bar /node_modules/foo/bar
NODE_PATH環境變量json
與PATH環境變量相似,NodeJS容許經過NODE_PATH
環境變量來指定額外的模塊搜索路徑。NODE_PATH
環境變量中包含一到多個目錄路徑,路徑之間在Linux下使用":"分隔,在Windows下使用";"分隔。例如定義瞭如下NODE_PATH
環境變量:
NODE_PATH=/home/user/lib:/home/lib
gulp
當使用require('foo/bar')
的方式加載模塊時,NodeJs依次嘗試如下路徑:
js /home/user/lib/foo/bar /home/lib/foo/bar
緩存
包:由多個子模塊組成的大模塊稱作包,全部子模塊放在同一個目錄裏。在組成一個包的全部子模塊中,須要一個入口文件,入口模塊的導出對象被稱做包的導出對象。服務器
測試目錄以下:函數
- node_modules/ - aoao/ - lib/ test1.js test2.js main.js package.json
各js文件內容以下:工具
//test1.js exports.create = function (){ return 'test1'; } //test2.js exports.create = function (){ return 'test2'; } //main.js var test1 = require('./test1'); var test2 = require('./test2'); exports.create = function(name) { return { name: name, test1: test1.create(), test2: test2.create() }; };
咱們的某一模塊須要使用包時須要加載包的入口模塊。咱們使用時,能夠直接引入口文件main.js
,而後經過reuqire('/aoao/main.js')
的方式獲得須要的對象,可是這樣的路徑不太符合咱們的使用習慣。在使用某個包時,路徑可以指向包目錄,即aoao
的話,看起來更像是一個總體。
package.json
經過package.json的方式,能夠自定義入口模塊的文件名和存放位置。==NodeJs會根據包目錄(node_modules/aoao)下的package.json
文件找到入口模塊所在位置。==
//package.json { "name": "zgatry", "main": "./lib/main.js" }
//testPackage.js做爲其餘模塊,調用了包「aoao」 var aoao = require('aoao'); console.log(aoao.create('zgatry'));
在Node環境下的測試結果:
index.js
若是入口文件名爲index.js的話,能夠直接經過包路徑來訪問。
測試目錄:
- aoao/ test1.js test2.js index.js
index.js文件
var test1 = require('./test1'); var test2 = require('./test2'); console.log(test1.create(), test2.create());
在Node環境下測試結果:
測試結果說明能夠直接經過包的路徑來訪問以index.js爲入口文件的包。
使用NodeJS編寫的東西,要麼是一個包,要麼是一個命令行程序,而前者最終也會用於開發後者。所以咱們在部署代碼時須要一些技巧,讓用戶以爲本身是在使用一個命令行程序。
一個標準的工程目錄
- /home/user/workspace/node-echo #工程目錄 - bin/ #存放命令行相關代碼 node-echo + doc/ #存放文檔 - lib/ #存放API相關代碼 echo.js - node_modules/ #存放三方包 +argv/ + tests/ #存放測試用例 package.json #元數據文件 README.md #說明文件
NPM是隨同NodeJs一塊兒安裝的包管理工具,能解決NodeJs代碼部署上的不少問題。
npm常見的用途
從上面三個用途展開說明:
下載三方包
下載前須要知道==包名==,而後執行如下語句:
npm install + 包名
三方包默認存放在工程目錄下的node_modules
目錄中,使用時直接require('包名')
就OK,緣由在上面的「包」已經有說明了。
若是須要依賴的包比較多,而重複執行上面的步驟顯得比較low,因此NPM在package.json文件中提供了dependencies
字段,來存放依賴。所以上面的代碼能夠改寫成:
npm install
這樣就能夠批量安裝三方包了。
當你寫好一個包而後上傳到NPM服務器而且你的包依賴了其餘三方包,目錄結構就會變成:
- node_modules/ # 使用者的node_modules目錄 - aoao/ # 你上傳的包 - node_modules/ # 你的包的依賴 ...
拿gulp來作例子,請看目錄結構
- node_modules/ - gulp/ + bin/ + completion/ + lib/ + node_modules/ CHANGELOG.md gulp.1 index.js LICENSE package.json README.md
下面基本就是筆記,照着原文看一遍。
安裝命令行程序
從NPM服務上下載安裝一個命令行程序的方法與三方包相似。NPM會自動建立好Linux系統下須要的軟鏈文件或Windows系統下須要的.cmd文件。
發佈代碼
第一次使用NPM發佈代碼須要註冊一個帳號。終端下運行npm adduser,以後按照提示作便可。帳號搞定後,接着咱們須要編輯package.json文件,加入NPM必需的字段。接着上邊node-echo的例子,package.json裏必要的字段以下。
{ "name": "node-echo", # 包名,在NPM服務器上需要保持惟一 "version": "1.0.0", # 當前版本號 "dependencies": { # 三方包依賴,須要指定包名和版本號 "argv": "0.0.2" }, "main": "./lib/echo.js", # 入口模塊位置 "bin" : { "node-echo": "./bin/node-echo" # 命令行程序名和主模塊位置 } }
以後,咱們就能夠在package.json
所在目錄下運行npm publish
發佈代碼了。
版本號
使用NPM下載和發佈代碼時都會接觸到版本號。NPM使用語義版本號來管理代碼。
語義版本號分爲X.Y.Z三位,分別表明主版本號、次版本號和補丁版本號。當代碼變動時,版本號按如下原則更新。 + 若是隻是修復bug,須要更新Z位。 + 若是是新增了功能,可是向下兼容,須要更新Y位。 + 若是有大變更,向下不兼容,須要更新X位。
版本號有了這個保證後,在申明三方包依賴時,除了可依賴於一個固定版本號外,還可依賴於某個範圍的版本號。例如"argv": "0.0.x"表示依賴於0.0.x系列的最新版argv。NPM支持的全部版本號範圍指定方式能夠查看官方文檔。
一些好用的npm命令:
npm update <package> #以把當前目錄下node_modules子目錄裏邊的對應模塊更新至最新版本。 npm cache clear #能夠清空NPM本地緩存,用於對付使用相同版本號發佈新版本代碼的人。
總結:
編寫NodeJs代碼前的準備工做:
node_modules
和NODE_PATH
來解耦包的使用方式和路徑。