npm是一個包管理工具,開源做者能夠把開源包發佈在平臺上供其餘人下載使用。前端的同窗基本都使用過npm,這裏就不作過多介紹。平常工做中npm的主要用途就是根據項目的package.json使用npm install去安裝依賴。前端
npm install能夠說是咱們使用最頻繁的一個指令。在npm5版本以前,npm install會根據package.json指定的依賴版本去進行安裝。但每每package.json中指定的是一個版本範圍,例如:vue
"dependencies": {
"packageA": "^2.0.0"
},
複製代碼
以上這個 ^2.0.0 指定的範圍是版本號大於等於2.0.0且大版本號爲2。即2.6.10這個是符合的,而3.0.0和1.0.0這種是不符合的。npm
這樣的範圍指定會致使一個問題:A新建了一個項目,生成了上面這份package.json文件,但A安裝依賴的時間比較早,此時packageA的最新版本是2.1.0,該版本與代碼兼容,沒有出現bug。後來B克隆了A的項目,在安裝依賴時packageA的最新版本是2.2.0,那麼根據語義npm會去安裝2.2.0的版本,但2.2.0版本的API可能發生了改動,致使代碼出現bug。json
這就是package.json會帶來的問題,同一份package.json在不一樣的時間和環境下安裝會產生不一樣的結果。bash
理論上這個問題是不該該出現的,由於npm做爲開源世界的一部分,也遵循一個發佈原則:相同大版本號下的新版本應該兼容舊版本。即2.1.0升級到2.2.0時API不該該發生變化。工具
但不少開源庫的開發者並無嚴格遵照這個發佈原則,致使了上面的這個問題。spa
一個新的事物的誕生都是爲了解決一個歷史問題code
基於這種情況,npm5推出了lock機制。在使用npm5.0.0以後的版本時,npm install後會自動生成package-lock.json文件,該文件記錄了當前此次install所安裝的依賴版本號。cdn
例如當package.json的依賴以下:blog
"dependencies": {
"vue": "^2.0.0"
},
複製代碼
install後自動生成的package-lock.json會指定安裝vue2.6.10版本(當前最新)
"dependencies": {
"vue": {
"version": "2.6.10",
"resolved": "https://registry.npm.taobao.org/vue/download/vue-2.6.10.tgz",
"integrity": "sha1-pysaQqTYKnIepDjRtr9V5mGVxjc="
}
}
複製代碼
package-lock.json至關於本次install的一個快照,它不只記錄了package.json指明的直接依賴的版本,也記錄了間接依賴的版本。
若是咱們想在不一樣環境和不一樣時間下每次install時安裝相同版本的依賴,咱們就能夠把package-lock.json帶上。
當package.json和package-lock.json同時存在時,npm install會去檢測package-lock.json指定的依賴版本是否在package.json指定的範圍內。若是在,則安裝package-lock.json指定的版本。若是不在,則忽略package-lock.json,而且用安裝的新版本號覆蓋package-lock.json。
舉個例子:
// package.json
"dependencies": {
"vue": "^2.0.0"
}
// package-lock.json
"dependencies": {
"vue": {
"version": "2.1.0",
"resolved": "https://registry.npm.taobao.org/vue/download/vue-2.1.0.tgz",
"integrity": "sha1-KTuj76rKhGqmvL+sRc+FJMxZfj0="
}
}
複製代碼
這種狀況下package-lock.json指定的2.1.0在^2.0.0指定的範圍內,npm install會安裝vue2.1.0版本。
// package.json
"dependencies": {
"vue": "^2.2.0"
}
// package-lock.json
"dependencies": {
"vue": {
"version": "2.1.0",
"resolved": "https://registry.npm.taobao.org/vue/download/vue-2.1.0.tgz",
"integrity": "sha1-KTuj76rKhGqmvL+sRc+FJMxZfj0="
}
}
複製代碼
這種狀況下package-lock.json指定的2.1.0不在^2.2.0指定的範圍內,npm install會按照^2.2.0的規則去安裝最新的2.6.10版本,而且將package-lock.json的版本更新爲2.6.10。
值得注意的是npm5一發布時並非採起這種install邏輯,在npm5.0到npm5.6之間install的邏輯發生了屢次變動,而在npm5.6以後一直沿用當前這種邏輯。
npm5以後的lock機制知足了要求鎖版本的開發者們的須要,咱們只須要拿到一份package-lock.json就能夠知道要安裝的依賴的具體版本號。但細心的同窗會發現當package-lock.json指定的版本號不在package.json指定的範圍內時,package-lock.json就會被更新覆蓋。這可不利於咱們去維持版本的固定。
所以後續npm也推出了npm ci的指令來解決這一問題,npm ci和npm i的不一樣之處在於:當package-lock.json指定的依賴版本不在package.json指定的依賴版本範圍內時,npm會報錯並取消安裝。
這樣咱們就不怕在package-lock和package.json不一致時發生覆蓋更新。
在npm5.6之後咱們就能夠放心大膽地使用package-lock.json文件來鎖版本,而在構建部署時可使用npm ci安裝命令來防止npm install的覆蓋更新問題。