【譯】關於你想知道的package-lock.json的一切

DearVikki發表於2018-12-04

【老文新譯:原文地址

前情提要

當你開心的將npm升到v5.x.x(原文時代)之後,一切都似乎還挺順利。誒…等等,一個新檔案被自動建立啦!這是啥?Package-lock.json。如果你有瀏覽它,會發現它長得類似package.json的依賴,但是冗長多啦。你想,乾脆不管它得了,可是最後總是會遇見關於依賴裝錯版本或者找不到依賴等等各式各樣的問題。許多人的解決方式都是刪掉package-lock.json,再跑一遍npm install。若是如此,package-lock.json存在的意義是啥?它的目的又是為了解決什麼呢?

概覽

  • 如果你用的是npm 5.0.0以上版本,package-lock.json檔案會自動建立。
  • package-lock被用來確保穩定安裝和依賴相容。
  • 為確保源一致,你必須提交package-lock檔案。
  • npm 5.1.x以上版本,package.json的權重大於package-lock.json,解決了一大頭疼源泉。
  • 不用手動刪去package-lock檔案然後再npm install再重新生成它啦。
  • 使用並遵循semver語義化版本。

背景

語義化版本

在一探package-lock究竟之前,你必須要理解semver。它是npm背後的小小功臣。你可以從這裡瞭解到npm是如何使用它的。概括來講,假若你在開發一個可供其它應用使用的應用,你必須說明每次升級變更會對第三方使用產生哪些影響。這就是語義化版本想要傳達的。一個版本有三部分:X, Y, Z,分別指代大版本,小版本,與查缺補漏版本。比如1.2.3,那麼就是大版本1,小版本2,bugfix版本3。bugfix版本不會影響任何功能,小版本變更往往是增加新功能,也不會影響使用。而大版本變更往往會帶來使用層面不相容的情況,需要再做調整。(想想webpack每次升級的時候!)

包管理

正是為了讓包管理變簡單,npm出現了。一個專案可能有上百個依賴,每個依賴又有上百個依賴。為了你不陷入依賴地獄,只需簡單幾行命令,npm就可以安裝並管理這些依賴,大大節省了時間。

當你使用npm安裝一個包(並儲存它)的時候,package.json裡就自動新增了一條資訊,包括包名和其版本。npm當然也支援版本的萬用字元。npm預設安裝最新版本,然後在其版本號之前新增一個"^"符。比如“^1.2.12”,它表明最低應使用1.2.12版本,並且在這之上,擁有相同大版本號的任何版本都是OK的。畢竟小版本和bugfix版本不會對使用造成任何影響,所以用任何相同大版本的更高階版本都很安全。可以從這裡瞭解semver萬用字元的更多資訊,以及npm的semver計算器。

多人專案

Package.json的真正好處在於,任何人都可以通過這個檔案生成一個裝有專案所需所有依賴的資料夾。但是我們來看一下,哪些地方可能出問題呢?

就來新建一個使用express的專案吧。執行npm init後,安裝express:npm install express — save。我撰文時express最高版本是4.15.4。所以“express”: “^4.15.4”被寫進package.json裡,依賴也已經裝好了。不過第二天,可能express的維護者釋出了一個bugfix版本,所以最新版本又變成了4.15.5。如果這時我同事clone了這個專案,並且執行npm install,因為4.15.5的大版本號沒變,所以他裝的版本就會是最新的4.15.5。我們都安裝了express,不過是不同的版本。按道理講他們是互相相容的,但是可能好巧不巧,這個被修復的bugfix剛好就影響到我們使用的功能了,那麼我們分別執行自己的專案時就會出現不同的結果。這是個問題!

Package-lock

目標

Package-lock的出現就是為了解決上述問題的!也就是從同一份package.json檔案可能安裝出不一樣的結果。Package-lock.json自npm 5.x.x後加入,所以只要你沒禁止掉它(注:可以從.npmrc設定package-lock = false喔),它都會自動生成。

格式

Package-lock包括package.json裡所例舉的包的應安裝版本,安裝地址(URI),校驗包完整性的hash,其需要的子包,以及依賴列表。express的package-lock條目如下:

"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下例舉的每個包,都在package-lock下擁有一份同樣的條目。

所以npm其實現在是用package-lock.json來決定如何安裝依賴的!因為package-lock寫明瞭包的安裝版本,地址,也做了包完整性校驗,以及例舉了包的所有子依賴,所以按照package-lock來裝模組的話,一定會得到一模一樣的結果

爭論

既然packge-lock是用來解決問題的,那為什麼還有許多質疑它存在,以及關於如何禁止它生成的討論呢?

npm5.x.x以前,package.json是專案的唯一真理來源。package.json說啥就是啥!npm使用者喜歡並習慣僅維護package.json。但是,當package-lock出現後,它和很多人期望的背道而馳了!如果有同一份package和package-lock,package.json的修改並不會影響到package-lock。

於是就出現了更改package.json後,安裝未生效的情況,需要移除package-lock再生成一份,由此引發了很多爭論。可以從這份有趣的reop時間線上看出端倪。有的人覺得還是得以package.json為準,有的人又覺得既然package-lock被創造出來了,那就以新的為準唄。最後這份爭論以PR#17508劃上句號。npm決定,如果package.json上發生過改動,安裝時package.json的權重就會超過package-lock。這個決定隨著npm v5.1.0釋出,自2017年7月5日起即日執行~

相關文章