語義化版本
在一探package-lock.json
究竟之前,你必須要理解semver。它是npm
背后的小小功臣。你可以從這里了解到npm
是如何使用它的。概括來講,假若你在開發一個可供其它應用使用的應用,你必須說明每次升級變更會對第三方使用產生哪些影響。這就是語義化版本想要傳達的。一個版本有三部分:X, Y, Z,分別指代大版本,小版本,與查缺補漏版本。比如1.2.3,那么就是大版本1,小版本2,bugfix版本3。bugfix版本不會影響任何功能,小版本變更往往是增加新功能,也不會影響使用。而大版本變更往往會帶來使用層面不兼容的情況,需要再做調整。(想想webpack每次升級的時候!)
NPM包管理
正是為了讓包管理變簡單,npm
出現了。一個項目可能有上百個依賴,每個依賴又有上百個依賴。為了你不陷入依賴地獄,只需簡單幾行命令,npm
就可以安裝並管理這些依賴,大大節省了時間。
- 符號
^
:表示安裝不低於該版本的應用,但是大版本號需相同,例如:vuex: "^3.1.3"
,3.1.3
及其以上的3.x.x
都是滿足的。 - 符號
~
:表示安裝不低於該版本的應用,但是大版本號和小版本號需相同,例如:vuex: "^3.1.3"
,3.1.3
及其以上的3.1.x
都是滿足的。 - 無符號:無符號表示固定版本號,例如:
vuex: "3.1.3"
,此時一定是安裝3.1.3
版本。
為什么需要package-lock.json
npm install 的輸入是 package.json,它的輸出是一棵 node_modules 樹。理想情況下,npm install 應該像純函數一樣工作,對於同一個 package.json 總是生成完全相同的 node_modules 樹。在某些情況下,確實如此。但在其他很多情況中,npm 無法做到這一點。有以下原因:
- 不同版本的 npm 的安裝算法不同。
- 某些依賴項自上次安裝以來,可能已發布了新版本,因此將根據 package.json 中的 semver-range version 更新依賴。
- 某個依賴項的依賴項可能已發布新版本,即使您使用了固定依賴項說明符(1.2.3 而不是 ^1.2.3),它也會更新。
為了在不同的環境下生成相同的 node_modules,npm 使用 package-lock.json 或 npm-shrinkwrap.json。這兩個文件都被稱為 lockfiles。無論何時運行 npm install,npm 都會生成或更新 lockfiles。以下只討論其中的 package-lock.json。
在.npmrc文件中設置package-lock = true,會在install 的時候產生package-lock.json的文件
不同 npm 版本下 npm i 的規則
-
npm 5.0.x 版本:不管 package.json 中依賴是否有更新,npm i 都會根據 package-lock.json 下載。針對這種安裝策略,有人提出了這個 issue - #16866 ,然后就演變成了 5.1.0 版本后的規則。
-
5.1.0 版本后:當 package.json 中的依賴項有新版本時,npm install 會無視 package-lock.json 去下載新版本的依賴項並且更新 package-lock.json。針對這種安裝策略,又有人提出了一個 issue - #17979 ,參考 npm 貢獻者 iarna 的評論,得出 5.4.2 版本后的規則。
-
5.4.2 版本后:
-
如果只有一個 package.json 文件,運行
npm i
會根據它生成一個 package-lock.json 文件。 -
如果 package.json 的 semver-range version 和 package-lock.json 中版本兼容,即使此時 package.json 中有新的版本,執行
npm i
也還是會根據 package-lock.json 下載 - 實踐場景1。 -
如果手動修改了 package.json 的 version ranges,且和 package-lock.json 中版本不兼容,那么執行
npm i
時 package-lock.json 將會更新到兼容 package.json 的版本 - 實踐場景2。
-
實踐
npm 版本:6.4.1
場景1
-
假設剛從遠程倉庫克隆一個項目,此時本地 node_modules 還不存在,package.json 和 package-lock.json 如下。已知 superagent 3.x.x 的最新版本是 3.8.3,那么運行 npm install 是根據 package-lock.json 中指定的版本 3.5.1 去下載還是根據 package.json 去下載最新的 3.x.x ?
// package.json "dependencies": { "superagent": "^3.5.1" } // package-lock.json { "superagent": { "version": "3.5.1", "resolved": "https://npm.garenanow.com/superagent/-/superagent-3.5.1.tgz", "integrity": "sha1-Ck+u/aM2d3d4iDR917TSH0EMhxs=", "requires": { "component-emitter": "^1.2.0", "cookiejar": "^2.0.6", "debug": "^2.2.0", "extend": "^3.0.0", "form-data": "^2.1.1", "formidable": "^1.1.1", "methods": "^1.1.1", "mime": "^1.3.4", "qs": "^6.1.0", "readable-stream": "^2.0.5" } }, } 復制代碼
結論:下載的是
3.5.1
。此時 package.json 和 package-lock.json 同時存在,package.json 的 version 是^3.5.1
,package-lock.json 的 version 是3.5.1
,並且當前 node_modules 中下載的也是3.5.1
。
場景2
- 接着場景1,然后手動修改 package.json 中 superagent 的版本為
^5.1.0
,再執行 npm i,發現不管有沒有刪除已有的 node_modules,package-lock.json 中 superagent 的版本都變成了5.1.0
,node_modules 中的也變成了5.1.0
。
鏈接:https://juejin.cn/post/6844903903193104398