想閱讀更多優質文章請猛戳GitHub博客,一年百來篇優質文章等着你!html
若是你已經將節點包管理(npm)更新到版本5.x.x,看起來一切彷佛都很順利。等等,這是什麼?用 npm 初始化項目的會自動建立了一個新文件 package-lock.json
。若是打開它,它看起來有點像 package.json
的依賴項,但更冗長。咱們決定忽略它,繼續開發項目。最終,咱們有時會遇到依賴項的問題,找不到,或者安裝了錯誤的版本。大多數人最終都會刪package-lock.json
和運行「npm install」。那麼,爲何要有它呢? 它應該作什麼? 它其實是作什麼的?前端
npm install
並從新生成它在你瞭解 package-lock 甚至 package.jso n以前,你必須瞭解語義版本控制(semver)。 這是npm背後的天才,是什麼使它更成功。 你能夠在 此處 閱讀有關npm如何使用它的更多信息。簡而言之,若是你正在構建與其餘應用程序接口的應用程序,你應該告知你所作的更改將如何影響第三方與你的應用程序交互的能力。這是經過語義版本控制完成的,版本由三部分組成:X,Y,Z,分別是主要版本,次要版本和補丁版本。git
例如:1.2.3,主要版本1,次要版本2,補丁3。github
補丁中的更改表示不會破壞任何內容的錯誤修復。 次要版本的更改表示不會破壞任何內容的新功能。 主要版本的更改表明了一個破壞兼容性的大變化。 若是用戶不適應主要版本更改,則內容將沒法正常工做。express
npm 存在使管理包變得容易。你的項目可能有數百個依賴項,每一個依賴項都有一百個,爲了讓你的注意力遠離依賴地獄,經過 npm 管理,使用一些簡單的命令,你能夠安裝和管理這些依賴關係,幾乎沒必要考慮它們。npm
當您使用npm安裝包(並保存它)時,會在 package.json 中添加一個包含包名稱和應該使用的 semver的條目。默認狀況下,npm 安裝最新版本,並預先插入版本號,例如 「^1.2.12」,這表示至少應該使用版本 1.2.12,但任何高於此版本的版本均可以,只要它具備相同的主要版本,因爲次要版本和補丁編號僅表明錯誤修正和非破壞性添加, 你能夠安全地使用任何更高版本的同一主要版本。閱讀更多關於semver通配符的信息,請看 這裏。json
在 package.json 中定義這樣的依賴項的真正好處是,任何有權訪問 package.json 的人均可以建立一個包含運行應用程序所需模塊的依賴項文件夾,可是讓咱們來看看事情可能出錯的具體方式。安全
假設咱們建立了一個將使用 express 的新項目。 運行npm init
後,咱們安裝express:npm install express - save
。在編寫代碼時,最新的版本是4.15.4,因此 「express」:「^ 4.15.4」做爲個人package.json中的依賴項添加,而且個人電腦安裝了確切的版本。cookie
如今也許明天,express 的維護者會發布 bug 修復,所以最新版本變爲4.15.5。 而後,若是有人想要爲個人項目作貢獻,他們會克隆它,而後運行`npm install。'由於4.15.5是具備相同主要版本的更高版本,因此爲它們安裝。 咱們都安裝 express ,但咱們倒是不一樣的版本。post
從理論上講,它們應該仍然是兼容的,但也許bugfix會影響咱們正在使用的功能,並且當使用Express版本4.15.4和4.15.5運行時,咱們的應用程序會產生不一樣的結果。
package-lock.json 的目的是避免上述狀況,其中從同一 package.json 安裝模塊會致使兩種不一樣的安裝。 在 npm
版本 5.x.x
中添加了 package-lock.json,所以若是你使用的是主要版本 5
或更高版本,除非您禁用它,不然它會自動生成。
package-lock 是 package.json 中列出的每一個依賴項的大型列表,應安裝的特定版本,模塊的位置(URI),驗證模塊完整性的哈希,它須要的包列表 ,以及依賴項列表。 讓咱們來看看 express 的列表是什麼:
"express": { "version": "4.15.4", "resolved": "https://registry.npmjs.org/express/-/express-4.15.4.tgz", "integrity": "sha1-Ay4iU0ic+PzgJma+yj0R7XotrtE=", "requires": { "accepts": "1.3.3", "array-flatten": "1.1.1", "content-disposition": "0.5.2", "content-type": "1.0.2", "cookie": "0.3.1", "cookie-signature": "1.0.6", "debug": "2.6.8", "depd": "1.1.1", "encodeurl": "1.0.1", "escape-html": "1.0.3", "etag": "1.8.0", "finalhandler": "1.0.4", "fresh": "0.5.0", "merge-descriptors": "1.0.1", "methods": "1.1.2", "on-finished": "2.3.0", "parseurl": "1.3.1", "path-to-regexp": "0.1.7", "proxy-addr": "1.1.5", "qs": "6.5.0", "range-parser": "1.2.0", "send": "0.15.4", "serve-static": "1.12.4", "setprototypeof": "1.0.3", "statuses": "1.3.1", "type-is": "1.6.15", "utils-merge": "1.0.0", "vary": "1.1.1" } },
能夠在「requires」部分中列出的每一個包中找到等效條目。
npm(^5.x.x.x)後的作法,npm 使用package-lock.json,而不是使用 package.json 來解析和安裝模塊。由於 package-lock 爲每一個模塊及其每一個依賴項指定了版本,位置和完整性哈希,因此它每次建立的安裝都是相同的。 不管你使用什麼設備,或者未來安裝它都可有可無,每次都應該給你相同的結果,這很是有用。
所以,若是引用 package-lock 是但願解決一個常見問題,爲何它的頂級搜索結果(除了npm文檔)都是關於禁用它或質疑它扮演的角色?
在npm 5.x.x以前,package.json 是項目的真實來源,npm 用戶喜歡這個模型,而且很是習慣於維護他們的包文件。 可是,當首次引入 package-lock 時,它的行爲與有多少人預期的相反。 給定一個預先存在的包和package-lock,對package.json的更改(許多用戶認爲是真實的來源)沒有同步到package-lock 中。
示例:包A,版本 1.0.0 在 package.json 和 package.lock.json 中。 在package.json中,A被手動編輯爲1.1.0版。 若是認爲 package.json 是真實來源的用戶運行 npm install
,他們會指望安裝 1.1.0版。 可是,安裝了1.0.0版,即便列出的 v1.1.0 是 package.json, 他們也但願安裝是 1.0.0版。
示例: package-lock.json 中不存在模塊,但它存在於 package.json 中,做爲一個將package.json 視爲真實來源的用戶,我但願可以安裝個人模塊。 可是,因爲 package-lock.json 不存在該模塊,所以未安裝該模塊,而且個人代碼因沒法找到模塊而失敗。
大部分時間,由於咱們沒法弄清楚爲何咱們的依賴關係沒有被正確安裝,要麼刪除了package-lock.json 並從新安裝,要麼徹底禁用 package-lock.json 來解決問題。
指望與真實行爲之間的這種衝突在 npm repo中引起了一個很是有趣的問題線索。 有些人認爲package.json 應該是事實的來源,有些人認爲,由於 package-lock 是 npm 用來建立安裝的東西,因此應該被認爲是事實的來源。 這場爭議的解決方案在於 PR#17508。 若是 package.json 已更新,Npm 維護者添加了一個更改,致使package.json 覆蓋 package-lock。 如今,在上述兩種狀況下,都會正確安裝用戶指望安裝的軟件包。 此更改是做爲npm v5.1.0的一部分發布的,該版本於2017年7月5日上線。
你的點贊是我持續分享好東西的動力,歡迎點贊!