• 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": {
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 安装一个新包
      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=="
        }
      }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    3.2 确定版本

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

    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=="
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    3.3 补丁版本升级

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

    在这里插入图片描述

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

    在这里插入图片描述

    3.4 次版本升级

    {
      "name": "test",
      "dependencies": {
        "pdfjs-dist": "^2.12.313"
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    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=="
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • package.json 文件更新结果
      在这里插入图片描述

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

    • package.json 改为 "pdfjs-dist": "^2.12.500"
    {
      "name": "test",
      "dependencies": {
        "pdfjs-dist": "^2.12.500"
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 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"
          }
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    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"
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 执行命令:npm i react -S
    • package.json 文件更新结果:新增一行 "react": "^18.2.0"
    {
      "name": "test",
      "dependencies": {
        "pdfjs-dist": "^2.12.313",
        "react": "^18.2.0"
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 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
  • 相关阅读:
    JavaScriptJQuery_jQuery简介
    【开发问题系列】CSV转Excel
    【luogu P2508】圆上的整点(高斯素数模板)
    代码随想录Day03 | 链表基础1 LeetCode T203 移除链表元素 T707设计链表 T206 反转链表
    CentOS 7 安装MySQL
    利用pycharm调试ssh远程程序,并实时同步文件
    在线实时监测离子风机的功能
    数据分析:单元2 NumPy数据存取与函数
    SkiaSharp 之 WPF 自绘 拖曳小球(案例版)
    详解PHP代码执行漏洞--无字母shell
  • 原文地址:https://blog.csdn.net/zhichaosong/article/details/119682473