是用nodejs寫的包管理生態系統css
windows 安裝完node一般會自動設置環境變量PATHnode
NODE_PATH = XXX\Node\nodejs
PATH = %NODE_PATH%\;%NODE_PATH%\node_modules;%NODE_PATH%\node_global;
複製代碼
若是不配置呢?git
error:node不是內部或外部命令,也不是可運行的程序 或批處理文件。算法
查看npm配置數據庫
npm config ls 或 npm config list
複製代碼
上面一樣列舉了npmrc(npm用戶配置文件)的地址npm
這裏面核心的是三項json
npm config set prefix "F:\office_software\nodejs\xxx_global"
複製代碼
npm config set registry "https://registry.npm.taobao.org"
複製代碼
另一個配置就是npm緩存的目錄windows
$ npm config get cache
C:\Users\Administrator\AppData\Roaming\npm-cache
複製代碼
npm-cache存放下載包的緩存(對應sha1計算後的內容也在裏面)緩存
npm config set cache "F:\office_software\nodejs\xxx_cache"
複製代碼
這兩個命令是同樣的,一個全寫一個簡寫bash
npm install 或 npm i
複製代碼
npm會根據package.json配置文件中的依賴配置下載安裝到項目下的node_modules目錄
npm i -g XXX
複製代碼
全局安裝,安裝後的包位於系統預設目錄下
這樣就安裝在了C:\Users\Administrator\AppData\Roaming\npm\node_modules目錄下
安裝的包將寫入package.json裏面的dependencies,dependencies:生產環境須要依賴的庫
好比:less和scss編譯用的包,只有開發時才用獲得,實際運行時並不用到,因此就不用放到生產環境依賴包中
安裝的包將寫入packege.json裏面的devDependencies,devdependencies:只有開發環境下須要依賴的庫
假如npm_pkg包已經寫好(裏面只要有個package.json就能夠),如
npm install ../npm_pkg
複製代碼
一般用來測試本地npm包
npm install ../npm_demo_cli -g
複製代碼
npm install還有不少其餘使用方式,不經常使用,就不一一介紹了。 具體請參照《官方文檔》
主版本號[MAJOR].次版本號[MINOR].修訂號[PATCH]
當主版本號升級後,次版本號和修訂號須要重置爲0,次版本號進行升級後,修訂版本須要重置爲0。
用到的語義化字符有: ~、>、<、=、>=、<=、-、||、x、X、*
'^2.1.1' // 2.x最新版本(主版本號鎖定)
'~2.1.1' // 2.1.x最新版本好(主和次版本號鎖定)
'>2.1' // 高於2.1版本的最新版本
'1.0.0 - 1.2.0' // 兩個版本之間最新的版本(必需要有空格)
'*' // 最新的版本號
'3.x' // 對應x部分最新的版本號
複製代碼
npm install默認安裝 ^x.x.x類型的版本,用於兼容大版本下最新的版本
執行工程自身preinstall
肯定首層依賴模塊
獲取模塊
若是npm-shrinkwrap.json和package-lock.json同時存在,則以npm-shrinkwrap.json爲主,忽略另外一個
獲取模塊內容
查找該模塊依賴
模塊扁平化
遍歷全部節點,逐個將模塊放在根節點下面,也就是 node-modules 的第一層。當發現有重複模塊時,則將其丟棄
這裏須要對重複模塊進行一個定義,它指的是模塊名相同且 semver 兼容。每一個 semver 都對應一段版本容許範圍,若是兩個模塊的版本容許範圍存在交集,那麼就能夠獲得一個兼容版本,而沒必要版本號徹底一致,這可使更多冗餘模塊在 dedupe 過程當中被去掉。
好比
node-modules 下 foo 模塊依賴 lodash@^1.0.0,bar 模塊依賴 lodash@^1.1.0,則 ^1.1.0 爲兼容版本。
而當 foo 依賴 lodash@^2.0.0,bar 依賴 lodash@^1.1.0,則依據 semver 的規則,兩者不存在兼容版本。會將一個版本放在 node_modules 中,另外一個仍保留在依賴樹裏。
安裝模塊
執行工程自身生命週期
最後一步是生成或更新版本描述文件(package.json和package-lock.json),npm install 過程完成。
若是這個npm還有其餘依賴包,會一併安裝(只會安裝dependencies部分)
devDependencies中的依賴並不會安裝
A@1
|-B@1.1
|-C@1
D@1
|-B@1.2
E@1
|-B@1.3
複製代碼
這個時候,由於解析的時候,B@1已經在根目錄了 那麼B@2就會成爲D@1中私有模塊,即
node_modules
|-A@1
|-B@1.3
|-C@1
|-D@1
|-E@1
複製代碼
A@1
|-B@1
|-C@1
D@1
|-B@2
E@1
|-B@2
複製代碼
這個時候,由於解析的時候,B@1已經在根目錄了 那麼B@2就會成爲D@1中私有模塊,即
node_modules
|-A@1
|-B@1
|-C@1
|-D@1
|-node_modules
|-B@2
|-E@1
|-node_modules
|-B@2
複製代碼
後面版本的npm包,即便是以前在私有目錄中安裝過,也一樣會重複安裝
那一樣版本的npm包會屢次安裝麼
npm 5版本引入了package.lock.json
即在npm install以後會在根目錄下生成一個package.lock.json文件
舉個例子
{
...
"babel-polyfill": {
"version": "6.26.0",
"resolved": "https://rcnpm.zhuanspirit.com/babel-polyfill/download/babel-polyfill-6.26.0.tgz",
"integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=",
"requires": {
"babel-runtime": "6.26.0",
"core-js": "2.6.5",
"regenerator-runtime": "0.10.5"
},
"dependencies": {
"regenerator-runtime": {
"version": "0.10.5",
"resolved": "https://rcnpm.zhuanspirit.com/regenerator-runtime/download/regenerator-runtime-0.10.5.tgz",
"integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg="
}
}
}
}
複製代碼
結構很簡單:
鎖定安裝時包的版本號,而且能夠上傳到git
保證每一個人安裝的依賴是同樣的
由於npm install -D xxx 以後,默認版本是向後兼容的
好比:
"dependencies": {
"core-js": "^3.2.0",
}
複製代碼
^3.2.0 即表示3.x版本中最新的版本
也就是說package.json中鎖定的實際上是大版本號,而小版本每次安裝都是取最新的。
假如說後面又發佈了3.x更高版本,那麼後面執行npm install同窗安裝的就是更高的版本了,好比3.5.0
固然,上面說的版本號規則都是所謂的「規則」,並無什麼強制校驗的措施,遵不遵照全憑自覺。因此頗有可能出現:
即便是小版本也會出現和以前版本不兼容的狀況。
因此,鎖定當前的npm包的版本號就頗有必要,package.lock.json 也就應運而生了。
那麼package.lock.json做用就是:鎖定npm包小版本號
問題:那npm install時,若是package.json和package-lock.json都存在,以哪一個爲主?
其實只有一條規則:==若是package-lock中的版本,在package.json範圍內,就以package-lock爲主,不然以package.json爲主==
好比:以core-js爲例子
1)場景一
package.json 中是 "^3.2.0", package-lock.json 中是 "3.1.0"
兼容範圍是3.2.0+版本,而3.1.0是在這範圍以外(比這小),因此安裝時以package.json的^3.2.0爲主,就會安裝3.x最新的版本(目前是3.5.0)
2)場景二
package.json 中是 "^3.1.0", package-lock.json 中是 "3.2.0"
兼容範圍是3.1.0+版本,而3.2.0正符合這個範圍,因此安裝就按照package-lock.json中指定的3.2.0版本
node爲script指令提供了生命週期鉤子
舉個例子,好比package.json中:
"scripts": {
"aaa": "echo \"Log: aaa specified\""
}
複製代碼
當執行下面腳本時
npm run aaa
複製代碼
實際上等價於際執行
if (preaaa) npm run preaaa
npm run aaa
if (postaaa) npm run postaaa
複製代碼
因此,進一步實驗
"scripts": {
"aaa": "echo \"Log: aaa specified\"",
"preaaa": "echo \"Log: preaaa specified\"",
"postaaa": "echo \"Log: postaaa specified\" & exit 1"
}
複製代碼
結果爲:
E:\work\npm_test>npm run aaa
> npm_test@1.0.0 preaaa E:\work\npm_test
> echo "Log: preaaa specified"
"Log: preaaa specified"
> npm_test@1.0.0 aaa E:\work\npm_test
> echo "Log: aaa specified"
"Log: aaa specified"
> npm_test@1.0.0 postaaa E:\work\npm_test
> echo "Log: postaaa specified"
"Log: postaaa specified"
複製代碼
npm run執行時,會把./node_modules/.bin/ 目錄添加到執行環境的 PATH 變量中
這樣,即使只在當前項目裏安裝了某個包,npm run同樣能夠調用
執行 script 腳本若是須要傳入參數,須要在命令後加 -- 標明, 如:
npm run dev -- -r main
複製代碼
將自定義參數r=main傳入dev命令中
在執行的script 腳本中,能夠直接使用process.env對象,它會返回全部和執行環境相關的信息
注:獲取屬性時,若是是帶有中劃線的屬性,須要改爲下劃線,如core-js須要改爲core_js
刪除npm_cache下全部緩存文件
刪除後,package-lock.json文件中就找不到對應的sha1內容了,就會強制從新從服務器拉取npm包
從新計算npm_cache下全部緩存文件是否與sha1值匹配,若是不匹配可能刪除
刪除package.lock.json文件
npm cache clean --force強制刪除緩存中的npm包