【问题标题】:Why does `npm install` add / remove caret (^) to / from version numbers?为什么`npm install` 在版本号中添加/删除插入符号(^)?
【发布时间】:2019-06-03 03:00:13
【问题描述】:

我有一个项目,我使用两台不同的笔记本电脑进行工作。有时我会在我的项目中添加额外的包,所以我必须使用npm install <package-name> (duh)。当我这样做时,我git push 更新了新的package.jsonpackage-lock.json 文件,当我切换计算机时,我必须git pull 进行这些更改,然后再次运行npm install 以将该包放到另一台计算机上。

我最近注意到并开始关心一台笔记本电脑不断在每个软件包版本号的开头添加插入符号 (^)。例如:

一台计算机将软件包版本#s 设置为如下所示:

"regexpu-core": {
  "version": "1.0.0",
  "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz",
  "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=",
  "requires": {
    "regenerate": "1.4.0",
    "regjsgen": "0.2.0",
    "regjsparser": "0.1.5"
  }
},

另外设置包版本#s如下:

"regexpu-core": {
  "version": "1.0.0",
  "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz",
  "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=",
  "requires": {
    "regenerate": "^1.2.1",
    "regjsgen": "^0.2.0",
    "regjsparser": "^0.1.4"
  }
},

我知道插入符号 (^) 表示版本不是 100% 精确,但我想弄清楚为什么我的不同笔记本电脑会为软件包版本创建不同的格式!我检查了this SO question,它对~^ 之间的差异有一些很好的解释,但我没有找到任何解释为什么npm 有时会添加或删除插入符号(^)。我还查看了this npm issue on Github,它建议查看npm 配置设置,但我的两台笔记本电脑都具有相同的设置:

  • npm config get save = true(两台电脑)
  • npm config get save-prefix = ^(两台电脑)
  • npm config get save-exact = false(两台电脑)

一台笔记本电脑正在运行npm 版本5.6.0,但我刚刚将其更新为6.5.0。另一台计算机运行版本6.4.1,但我也将其更新为6.5.0。我尝试在两台计算机上的项目中运行npm install,但我仍然发现一台计算机总是删除^,而另一台总是添加^

如果我遗漏了什么,请告诉我。感谢您的帮助!

【问题讨论】:

    标签: npm npm-install


    【解决方案1】:

    编辑:根据问题 #20434 中的讨论,这是使用 npm >=6.0.0 设计的。

    为什么会这样? @rarkinsthis comment 中详细解释了发生这种情况的原因(及其优势)。为方便起见,他的评论引述如下(逐字):

    假设您使用依赖项“aaa”、“bbb”和“ccc”的固定版本。假设他们每个人都像这样依赖“zzz”:

    • aaa 依赖于 zzz@^1.0.0
    • bbb 依赖于 zzz@^1.1.0
    • ccc 依赖于 zzz@^1.0.1

    即他们三个都依赖于 zzz 的范围,而不是一个确切的版本。

    假设zzz的最新版本是1.5.0。

    在此更改之前和之后,很明显 zzz 的解析版本应该是 1.5.0,因此唯一的区别是 package-lock.json 的结构和记录此子依赖项的方式。

    之前,lock 文件会显示它们三个都依赖于 zzz@1.5.0,而 z 的解析版本是 1.5.0。

    现在,它记录了每个依赖项的实际“原始”依赖版本(例如 ^1.0.0、^1.1.0 等),但仍将 z 的解析版本显示为 1.5.0。 em>

    然后考虑一下 zzz@1.5.1 发布后会发生什么:

    之前,锁定文件需要在所有四个位置从 z@1.5.0 更新到 z@1.5.1。

    现在,锁定文件只需要将 z 的解析版本更新为 1.5.1,而依赖项可以保留 ^1.0.0、^1.1.0 和 ^1.0.1,因为它们没有改变了。

    正如我之前在线程中提到的,在这两种情况下您仍然会得到完全相同的 node_modules。新方法的优点是:

    1. 您可以看到依赖项实际需要什么(例如,一个范围,而不是一个确切的版本)。以前,您无法判断 aaa 是否确实需要 zzz@1.5.0 或者它是 zzz@^1.0.0。

    2. 锁文件中没有改变四行,而你只得到了一行。流失更少,发生的事情更清楚。

    顺便说一句,yarn 使用与yarn.lock 类似的概念。例如这是一个示例,其中@sindresorhus/is 被固定,但它的子依赖符号可观察不是:

    "@sindresorhus/is@0.10.0":
     version "0.10.0"
     resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.10.0.tgz#f42dd6a9d12cd79fa6f53b27cf5bea3a30d2cafa"
     dependencies:
       symbol-observable "^1.2.0"
    

    原答案:

    git pull 修改后的 package.jsonpackage-lock.json 到计算机二尝试在安装前删除 node_modules 目录再次打包。

    例如:

    1. 首先cd 到您计算机 2 上的项目目录。

    2. 运行以下命令删除现有的 node_modules 目录:rm -rf node_modules

    3. 然后运行:npm install

    或者您可以使用&& 运算符链接上述两个命令:

    rm -rf node_modules && npm install
    

    【讨论】:

    • 这不能回答问题 why npm 从npm i 的锁定文件的版本中添加/删除插入符号 (^) .. 太糟糕了,因为我运行遇到相同的问题并且不需要解决方法,但我想知道为什么会发生这种情况(以及如何在有/没有 node_modules 目录的情况下使其保持一致)
    • @KlaasvanderWeij - 我建议要么;问一个新的 SO 问题并提供对此问题的参考,或者直接通过他们的 Github 存储库询问 npm。但是,首先阅读问题#20434 的cmets。根据 cmets; AB,它是使用 npm >=6.0.0 设计的,即它是故意的。评论 C 提供了有关 npm 为何这样做的更多详细信息。
    • 感谢您指出 GitHub 问题,确实评论 C 详细解释了 为什么
    猜你喜欢
    • 2019-06-23
    • 2016-05-02
    • 2017-11-25
    • 2020-07-06
    • 2017-01-10
    • 1970-01-01
    • 2020-03-24
    • 2018-09-13
    • 1970-01-01
    相关资源
    最近更新 更多