詳解package-lock.json的作用

詳解package-lock.json

我們都知道package.json除了配置快捷的node script腳本, 最主要的作用還是: 用於記錄下當前項目所應用到的依賴包, 但是既然都已經有了package.json文件了, 那麼為什麼項目中還需要一個package-lock.json呢? 本文就來為您詳細分析!


package-lock.json的作用

作用: 鎖定安裝時的包的版本號及包的依賴的版本號, 以保證其他所有人人在使用 npm install 時下載的依賴包都是一致的

比如說:
我下載了A依賴v1.0.0版本, 同時A依賴又是依賴與B依賴v1.3.2版本C依賴v2.0.3版本開發的

那麼對於package.json的話只會在dependencies 或者 devDependencies中記錄類似下的內容:

{
    "dependencies": {
        "依賴A": "^1.0.0"
    }
}

那麼下次安裝依賴A或許會出現以下情況:

  1. 依賴A的下載的版本為: 1.最新版.最新版, 導致項目出現bug
  2. 依賴A所依賴的B依賴C依賴下載了別的版本, 導致依賴A出現bug, 進而導致項目出現bug

packag.json只單純記錄本項目的依賴, 而沒有記錄下依賴的依賴, 並且依賴之間的版本號又沒有明確固定, 導致無法保證依賴環境一致

而package-lock.json的出現就是解決上述問題, 它會詳細的記錄項目依賴的版本號及依賴的依賴的版本號, 如以下所示:

{
  "name": "test",
  "version": "1.0.0",
  "lockfileVersion": 2,
  "requires": true,
  "packages": {
    "": {
      "name": "test",
      "version": "1.0.0",
      "license": "ISC",
        "dependencies": {
            "依賴A": "^1.0.0"
        }
    },
    "node_modules/依賴A": {
        "dependencies": {
            "B依賴": "^1.3.2",
            "C依賴": "^2.0.3"
        }
    }
  }
}

版本號的定義規則與前綴對安裝的影響

根據GNU中對版本號的定義規則:

中文版:
主版本號 . 子版本號 [ .修正版本號 [ .編譯版本號 ] ]

英文版:
Major_Version_Number . Minor_Version_Number [ .Revision_Number [ .Build_Number ] ]

英文簡化版:
Major . Minor . [ .Revision [.Build] ]


package.json中的前綴^符號 ~符號 *符號代表了對包安裝版本的不同策略, 下面的示例都通過下載vue2進行演示

  1. ^符號的意思: 版本號中最左邊的非0數字的右側都用最新的版本數

    • 例如: package.json中包版本為^2.1.0, 則下次會下載的版本為2.6.14 (2.最新.最新)
    • 例如: package.json中包版本為^0.7.1, 則下次會下載的版本為0.7.6 (0.7.最新)
    • 例如: package.json中包版本為^0.6.0, 則下次會下載的版本為0.6.0 (0.6.最新)
  2. ~符號的意思: Major永遠準確安裝, Minor給出的則準確安裝否則裝最新, Revision永遠裝最新

    • 例如: package.json中包版本為~2.0.3, 則下次會下載的版本為2.0.8 (2.0.最新)
    • 例如: package.json中包版本為~0, 則下次會下載的版本為0.12.16 (0.最新.最新)
    • 例如: package.json中包版本為~3.1, 則下次會下載的版本為3.1.5 (3.1.最新)
  3. *符號的意思: 直接下載這個包的最新版本

    • 例如: package.json中包版本為*, 則下次會下載的版本為2.6.14 (vue2的最新版)
  4. x符號的意思: x佔位開始, 全部使用最新

    • 例如: package.json中包版本為"2.3.x", 則下次會下載的版本為2.3.4 (2.3.最新)
    • 例如: package.json中包版本為"2.x.x", 則下次會下載的版本為2.6.14 (2.最新.最新)
    • 例如: package.json中包版本為"x.x.x", 則下次會下載的版本為2.6.14 (最新.最新.最新)
    • 例如: package.json中包版本為"x", 則下次會下載的版本為2.6.14 (最新.最新.最新)
  5. 精準版本號安裝

    npm i [email protected] # 下載Vue的2.6.14版本
    

這裡只列出幾種常見的, 具體的可到這篇博文中參考


改動package.json後依舊能改變項目依賴的版本

網上有很多博文說在npm版本5之後, 不能直接修改package.json中依賴包的版本來改變項目的安裝, 因為項目版本已經被鎖定在package-lock.json, 因此只能通過npm i 依賴@版本號的方法來改變版本

但是據我實際操作, 在npm版本為(v7.24.0), 直接修改package.json中依賴包的版本可以改變項目的安裝, 並且會更新到package-lock.json中


當前項目的真實版本號應該以package-lock.json為標準

示例:
我本地的項目1的package.json

{
  "name": "project1",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "less": "^3.8.0"
  }
}

張三想在他那運行我的項目, 為此他只將package.json複製到他的機器上然後運行npm i命令安裝項目運行所需的環境依賴

會出現以下情況: package.json中less編譯器的版本並沒變(還是 ^3.8.0), 但是less編譯器的實際版本卻是3.13.1, 即3大版本中的最新版, 再看自動生成的package.lock.json就會發現版本為3.13.1, 與實際版本相同, 所以package-lock.json中的依賴版本才是最為真實的, 不能盲目相信package.json

張三 npm i 後項目1的package.json

{
    "name": "project1",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
      "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
      "less": "^3.8.0"
  }
}

張三npm i後項目1的package.lock.json

{
    "less": {
      "version": "3.13.1"   // 這才是真實版本號
    }
}

package.lock.json的生成、更新、使用時機

  1. 生成時機:
    • 當項目有package.json文件並首次執行npm install安裝後, 會自動生成一個package-lock.json文件, 該文件裏面記錄了package.json依賴的模塊,以及依賴的依賴。並且給每個依賴標明了版本, 獲取地址和哈希值, 使得每次安裝都會出現相同的結果, 不管你在什麼機器上面或什麼時候安裝
  2. 更新時機
    • 使用命令重新安裝特定版本的包npm i [email protected]
    • 在package.json中修改依賴版本後, 執行npm install
  3. 使用時機
    • 執行npm install時, 與package.json共同確定依賴包及依賴包的依賴的精確的版本號

總結

  1. package.json用於告訴npm項目運行需要哪些包, 但包的最終安裝的版本不能夠只依靠這個文件進行識別, 還需以package-lock.json為準
  2. package.json中修改版本號會影響package-lock.json, 並且package.json比package.lock.json的優先級高, 如果package.json中less版本為^1.0.0 , package-lock.json中less版本為2.1.2, 則最終安裝的less版本為1.7.5, package-lock.json中less即其依賴的包將被從2.1.2退回到1.7.5`的狀態
  3. 為了保證該項目的環境依賴一致, 在項目移動時需要同時複製 package.json 和 package.lock.json 兩個文件
  4. 不要輕易動package.json與package-lock.json

也許您最終還有疑問: 既然package.json會影響package-lock.json, 那後者lock的意義在哪?

我是這樣理解的:

  1. package.json確定了項目依賴的版本, 但是沒有lock住依賴的依賴的版本
  2. 而package-lock.json就是用來lock住項目依賴的依賴


全文到此結束, 希望對您有幫助~~~