package-lock.json那些事

package-lock.json 在多人开发时经常冲突,该如何解决才能保证线上质量?package.json 如何定义才能符合我们的预期?
本文通过实验来探究包版本管理最佳实践,测试版本:node v12.20.0 (npm v6.14.8)

一、问题

  1. 什么时候用到
  2. 什么时候更新
  • 正常 npm i 会更新 lock 文件吗
  • npm i xxx -S 会更新 lock 文件吗
  • 删掉一个包会更新吗
  • package.json 锁死后,lock 文件还会更新吗
  • lock文件是1.1.0,package.json从^1.0.0 改到 ^1.0.1
  1. 怎么强制更新
  2. cnpm、pnpm 影响

二、说明

2.1 package.json 规则

  • 如果写入的是 〜0.13.0,则只更新补丁版本:即 0.13.1 可以,但 0.14.0 不可以。
  • 如果写入的是 ^0.13.0,则要更新补丁版本和次版本:即 0.13.1、0.14.0、依此类推。
  • 如果写入的是 0.13.0,则始终使用确切的版本。

2.2 package-lock.json 作用

  • npm 版本是 5+,会自动生成 package-lock.json
  • 简单来说就是锁定安装模块的版本号,例如下图锁定二级依赖项的版本,保证版本稳定
    在这里插入图片描述

三、实验

3.1 正常新安装

  • 我们用 pdfjs-dist 这个包来做测试,目前最新版 2.15.349
    在这里插入图片描述
    在这里插入图片描述

  • 空项目的 package.json 如下

{
  "name": "test",
  "dependencies": {
  }
}
  • 安装一个新包
    npm i pdfjs-dist -S

  • 安装结果,lock 文件为 2.15.349 版本
    在这里插入图片描述

{
  "name": "test",
  "requires": true,
  "lockfileVersion": 1,
  "dependencies": {
    "dommatrix": {
      "version": "1.0.3",
      "resolved": "http://bnpm.byted.org/dommatrix/-/dommatrix-1.0.3.tgz",
      "integrity": "sha512-l32Xp/TLgWb8ReqbVJAFIvXmY7go4nTxxlWiAFyhoQw9RKEOHBZNnyGvJWqDVSPmq3Y9HlM4npqF/T6VMOXhww=="
    },
    "pdfjs-dist": {
      "version": "2.15.349",
      "resolved": "http://bnpm.byted.org/pdfjs-dist/-/pdfjs-dist-2.15.349.tgz",
      "integrity": "sha512-EeCfqj6xi4/aegKNS7Bs+TCg3Y5gmKmG0s/5xXI0PqWW66x+Nm7iFXBpVcup7HnR8sNDm+5NESfFr8T6DeWp9Q==",
      "requires": {
        "dommatrix": "^1.0.3",
        "web-streams-polyfill": "^3.2.1"
      }
    },
    "web-streams-polyfill": {
      "version": "3.2.1",
      "resolved": "http://bnpm.byted.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz",
      "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q=="
    }
  }
}

3.2 确定版本

  • 我们选取最近两年下载量最高的版本 2.12.313 写死
    在这里插入图片描述
{
  "name": "test",
  "dependencies": {
    "pdfjs-dist": "2.12.313"
  }
}

npm i 安装结果

  • pdfjs-dist 使用了固定的 2.12.313 版本
  • 竟然没有其他依赖,这可能也是使用量高的原因?
    在这里插入图片描述
  • package-lock.json 结果
{
  "name": "test",
  "requires": true,
  "lockfileVersion": 1,
  "dependencies": {
    "pdfjs-dist": {
      "version": "2.12.313",
      "resolved": "http://bnpm.byted.org/pdfjs-dist/-/pdfjs-dist-2.12.313.tgz",
      "integrity": "sha512-1x6iXO4Qnv6Eb+YFdN5JdUzt4pAkxSp3aLAYPX93eQCyg/m7QFzXVWJHJVtoW48CI8HCXju4dSkhQZwoheL5mA=="
    }
  }
}

3.3 补丁版本升级

{
  "name": "test",
  "dependencies": {
    "pdfjs-dist": "~2.12.313"
  }
}
  • npm i 安装结果
    • package-lock.json 结果没有变化,因为 lock 文件锁死

在这里插入图片描述

  • npm upate 结果也没有变化,因为 2.12 下面只有 313 一个补丁版本

在这里插入图片描述

3.4 次版本升级

{
  "name": "test",
  "dependencies": {
    "pdfjs-dist": "^2.12.313"
  }
}

3.4.1 正常安装

  • npm i 安装结果
    • package-lock.json 因为版本锁死,依然没有变化

在这里插入图片描述

3.4.2 强制更新

  • npm update 更新结果
    • package-lock.json 根据 package.json 更新到最新
    • package.json 也相应的更新

在这里插入图片描述

  • package-lock.json 文件更新结果
{
  "name": "test",
  "requires": true,
  "lockfileVersion": 1,
  "dependencies": {
    "dommatrix": {
      "version": "1.0.3",
      "resolved": "http://bnpm.byted.org/dommatrix/-/dommatrix-1.0.3.tgz",
      "integrity": "sha512-l32Xp/TLgWb8ReqbVJAFIvXmY7go4nTxxlWiAFyhoQw9RKEOHBZNnyGvJWqDVSPmq3Y9HlM4npqF/T6VMOXhww=="
    },
    "pdfjs-dist": {
      "version": "2.15.349",
      "resolved": "http://bnpm.byted.org/pdfjs-dist/-/pdfjs-dist-2.15.349.tgz",
      "integrity": "sha512-EeCfqj6xi4/aegKNS7Bs+TCg3Y5gmKmG0s/5xXI0PqWW66x+Nm7iFXBpVcup7HnR8sNDm+5NESfFr8T6DeWp9Q==",
      "requires": {
        "dommatrix": "^1.0.3",
        "web-streams-polyfill": "^3.2.1"
      }
    },
    "web-streams-polyfill": {
      "version": "3.2.1",
      "resolved": "http://bnpm.byted.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz",
      "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q=="
    }
  }
}
  • package.json 文件更新结果
    在这里插入图片描述

3.4.3 次版本允许更新,并修改补丁版本

  • package.json 改为 "pdfjs-dist": "^2.12.500"
{
  "name": "test",
  "dependencies": {
    "pdfjs-dist": "^2.12.500"
  }
}
  • npm i 安装结果
    • package.json 无变化
    • package-lock.json 中更新为 2.15.349 最新版

这里需要特别注意的是,从确定版本改为次版本更新的时候(2.12.313 => ^2.12.313),是不会更新 lock 文件的;
但是从次版本更新改动补丁版本(^2.12.313 => ^2.12.500),就会触发 lock 更新;

在这里插入图片描述
在这里插入图片描述

3.5 安装新包

我们探索两种情况下安装新包:

  • 确定版本
  • 次版本

3.5.1 确定版本安装新包

  • 执行命令:npm i react -S
  • package.json 文件更新结果:新增一行 "react": "^18.2.0"
    在这里插入图片描述
  • package-lock.json 文件更新结果:pdfjs-dist 版本不受影响,新增 3 个 react 依赖包
    在这里插入图片描述
{
  "name": "test",
  "requires": true,
  "lockfileVersion": 1,
  "dependencies": {
    "js-tokens": {
      "version": "4.0.0",
      "resolved": "http://bnpm.byted.org/js-tokens/-/js-tokens-4.0.0.tgz",
      "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
    },
    "loose-envify": {
      "version": "1.4.0",
      "resolved": "http://bnpm.byted.org/loose-envify/-/loose-envify-1.4.0.tgz",
      "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
      "requires": {
        "js-tokens": "^3.0.0 || ^4.0.0"
      }
    },
    "pdfjs-dist": {
      "version": "2.12.313",
      "resolved": "http://bnpm.byted.org/pdfjs-dist/-/pdfjs-dist-2.12.313.tgz",
      "integrity": "sha512-1x6iXO4Qnv6Eb+YFdN5JdUzt4pAkxSp3aLAYPX93eQCyg/m7QFzXVWJHJVtoW48CI8HCXju4dSkhQZwoheL5mA=="
    },
    "react": {
      "version": "18.2.0",
      "resolved": "http://bnpm.byted.org/react/-/react-18.2.0.tgz",
      "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==",
      "requires": {
        "loose-envify": "^1.1.0"
      }
    }
  }
}

3.5.2 删除新安装包

  • package.json 文件删除一行 "react": "^18.2.0"
  • 执行命令:npm i
  • package-lock.json 文件更新结果:pdfjs-dist 版本不受影响,删除 3 个 react 依赖包在这里插入图片描述

3.5.3 次版本安装新包

  • 初始情况:package.json 改为次版本更新,但是 package-lock.json 文件依然为 2.12.313
{
  "name": "test",
  "dependencies": {
    "pdfjs-dist": "^2.12.313"
  }
}
  • 执行命令:npm i react -S
  • package.json 文件更新结果:新增一行 "react": "^18.2.0"
{
  "name": "test",
  "dependencies": {
    "pdfjs-dist": "^2.12.313",
    "react": "^18.2.0"
  }
}
  • package-lock.json 文件更新结果:同 「3.5.1 确定版本安装新包」,说明 lock 文件锁包的有效性

3.6 cnpm 影响

  • 初始状态:package.json 允许次版本更新 "pdfjs-dist": "^2.12.313"package-lock 文件写死 2.12.313 版本
  • 执行命令:cnpm inode_modules 包没有变动
  • 执行命令:rm -rf node_modules/ 删除已安装包
  • 执行命令:cnpm inode_modules 包更新到 2.15.349 最新版本,无视 package-lock.json 的锁定同时也不更新该文件
    在这里插入图片描述
  • 执行命令:npm inode_modules 包还原到 2.12.313 最新版本,package-lock.json 锁定有效
    在这里插入图片描述
  • 结论:cnpm 不支持(忽略)依据 package-lock.json 文件安装模块,默认依赖 package.json 进行安装

四、如何解决冲突

当两个同学都改动了 package.json 的时候,package-lock.json 文件的更新可能达到上千行的冲突,这时候如何处理?

  • 方式1:删掉 package-lock.jsonnpm i 重新安装?
    • 这种方式最不可取,相当于 lock 文件完全失效,全部重新安装
  • 方式2:手动合并?
    • 风险太高,integrity 字段 sha-512 校验如果改错会导致安装失败
  • 最佳实践
    • package-lock.json 还原到最近一个没有冲突的版本(例如上一版 master),解决 package.json 的冲突后(这个手动解决的风险可控),npm i 自动更新 lock 文件

五、结论

  1. 持续使用 npm,保证 lock 文件的有效性
  2. package-lock.json,不能手动修改,不能删除,降低风险
  3. package.json 锁死版本降低误更新的可能性(同时继续使用 lock 文件,双重保险)

参考文档

  • http://nodejs.cn/learn/the-package-lock-json-file
  • https://zhuanlan.zhihu.com/p/89093696
  • https://stackoverflow.com/questions/44297803/what-is-the-role-of-the-package-lock-json
  • https://docs.npmjs.com/cli/v8/configuring-npm/package-lock-json
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值