在我升级到最新的稳定版 node
和 npm
后,我尝试了 npm install moment --save
。它使用插入符号 ^
前缀将条目保存在 package.json
中。以前,它是一个波浪号 ~
前缀。
为什么在 npm 中进行这些更改?波浪号〜和插入符号^有什么区别?与其他人相比有什么优势?
npm config set save-prefix=''
。 (如果您愿意,请在引号中加上 ~
。)我个人会这样做并为生产中的事物进行收缩包装。
npm shrinkwrap
和 package-lock.json vs npm-shrinkwrap.json #toSaveYouAGoogle(或两个)的文档 -- fncomp 提到了 above 和 tehfoo below。此外,助记符:~
保持均匀,^
上升一点。
请参阅 NPM docs 和 semver docs:
~version “大约相当于版本”,将更新您到所有未来的补丁版本,而不增加次要版本。 ~1.2.3 将使用从 1.2.3 到 <1.3.0 的版本。
^version “与版本兼容”,将更新您到所有未来的次要/补丁版本,而不增加主要版本。 ^2.3.4 将使用从 2.3.4 到 <3.0.0 的版本。
请参阅下面的评论了解例外情况,特别是 for pre-one versions, such as ^0.2.3
我还想添加官方 npmjs 文档,其中描述了版本特异性的所有方法,包括问题中提到的方法
value desc ~version 大约相当于版本,即只接受新的补丁版本参见 npm semver - 波浪号范围 ^version 与版本兼容,即接受新的次要和补丁版本参见 npm semver - 插入符号范围版本必须与版本完全匹配 >version 必须大于 version >=version etc
上面的列表并不详尽。其他版本说明符包括 GitHub url 和 GitHub 用户存储库、本地路径和带有特定 npm 标签的包
官方文档
npm 文档 > package.json > 依赖项
npm 文档 > semver > 版本
服务器 (7)
1.2.0 || >=1.2.2 <1.3.0
:完全是 1.2.0,或从 1.2.2 到 1.3.0(含)的所有版本,但不能指定 1.2.1 或 1.3.1 及更高版本,以及也不是 1.1.x 及以下版本。
"Approximately equivalent to version"
和 "Compatible with version"
是描述 ~ 和 ^ 行为的令人沮丧的非特定方式。感谢@jgillich 提供实际答案!
npm 允许安装比指定版本更新的包。使用波浪号 (~
) 可为您提供错误修复版本,插入符号 (^
) 还可为您提供向后兼容的新功能。
问题是旧版本通常不会收到那么多错误修复,因此 npm 使用插入符号 (^
) 作为 --save
的默认值。
https://i.stack.imgur.com/JQ4ei.png
根据:"Semver explained - why there's a caret (^) in my package.json?"。
注意,这些规则适用于 1.0.0 以上的版本,并不是每个项目都遵循语义版本控制。对于 0.xx 版本,插入符号仅允许 patch 更新,即它的行为与波浪号相同。请参阅"Caret Ranges"
以下是对这些概念的直观解释:
来源:"Semantic Versioning Cheatsheet"。
伺服器
<major>.<minor>.<patch>-beta.<beta> == 1.2.3-beta.2
使用 npm semver 计算器进行测试。尽管对 ^(包括大于同一主要范围内的特定版本的所有内容)和 ~(包括大于同一次要范围内的特定版本的所有内容)的解释不是 100% 正确,但计算器似乎工作正常。
或者,使用 SemVer Check 代替,它不需要您选择包并且还提供解释。
允许或禁止更改
引脚版本:1.2.3。
使用 ^ (如头部)。允许在左侧第二个非零级别进行更新:^0.2.3 表示 0.2.3 <= v < 0.3。
使用〜(如尾巴)。如果省略,通常冻结最右边的级别或设置为零:
~1 表示 1.0.0 <= v < 2.0.0
~1.2 表示 1.2.0 <= v < 1.3.0。
~1.2.4 表示 1.2.4 <= v < 1.3.0。
省略最右边的级别:0.2 表示 0.2 <= v < 1。与 ~ 不同,因为:起始省略级别版本始终为 0 您可以设置起始主版本而不指定子级别。
起始省略级别版本始终为 0
您可以设置起始主要版本而不指定子级别。
所有(希望)的可能性
设置起始主级别并允许向上更新
* or "(empty string) any version
1 v >= 1
冻结专业级
~0 (0) 0.0 <= v < 1
0.2 0.2 <= v < 1 // Can't do that with ^ or ~
~1 (1, ^1) 1 <= v < 2
^1.2 1.2 <= v < 2
^1.2.3 1.2.3 <= v < 2
^1.2.3-beta.4 1.2.3-beta.4 <= v < 2
冻结次要级别
^0.0 (0.0) 0 <= v < 0.1
~0.2 0.2 <= v < 0.3
~1.2 1.2 <= v < 1.3
~0.2.3 (^0.2.3) 0.2.3 <= v < 0.3
~1.2.3 1.2.3 <= v < 1.3
冻结补丁级别
~1.2.3-beta.4 1.2.3-beta.4 <= v < 1.2.4 (only beta or pr allowed)
^0.0.3-beta 0.0.3-beta.0 <= v < 0.0.4 or 0.0.3-pr.0 <= v < 0.0.4 (only beta or pr allowed)
^0.0.3-beta.4 0.0.3-beta.4 <= v < 0.0.4 or 0.0.3-pr.4 <= v < 0.0.4 (only beta or pr allowed)
禁止更新
1.2.3 1.2.3
^0.0.3 (0.0.3) 0.0.3
注意:缺少major、minor、patch或指定beta
不带编号,与缺少级别的any
相同。
注意:当您安装以 0
为主要级别的软件包时,更新只会安装新的 beta/pr 级别版本!这是因为 npm
在 package.json
中将 ^
设置为默认值,并且当安装的版本类似于 0.1.3
时,它会冻结所有主要/次要/补丁级别。
https://docs.npmjs.com/misc/semver
https://docs.npmjs.com/files/package.json#dependencies
只要第一个数字(“主要”)至少为 1:
~
锁定主要和次要数字。当您准备好只接受错误修复(第三个数字的增量)但不想要任何其他更改,甚至不想要添加功能的小升级时使用它。
^
仅锁定主号码。当您愿意接收错误修复(第三个数字的增量)和添加功能但不应破坏现有代码的小升级(第二个数字的增量)时,使用它。但是,您不希望破坏现有代码的更改(第一个数字的增量)。
除此之外,^
是旧 npm 版本的 not supported,应谨慎使用。
因此,^
是一个很好的默认值,但它并不完美。我建议仔细选择和配置对您最有用的 semver 运算符。
(已修订以避免说“修复”和“错误修复”与“修复”的使用冲突,这是令人困惑的)
~
:合理地接近
~1.1.5: 1.1.0 <= accepted < 1.2.0
^
:兼容
^1.1.5: 1.1.5 <= accepted < 2.0.0
^0.1.3: 0.1.3 <= accepted < 0.2.0
^0.0.4: 0.0.4 <= accepted < 0.1.0
^0.1.3
只接受版本 0.1.x
而不会接受 0.2.0
,即使这是一个小的增量。此行为等效于 ~0.1.3
。这种行为背后的原因是零版本的软件包仍然被认为是不稳定的。用 semver.org, #4 的话来说,“任何事情都可能随时改变”(包括向后不兼容的改变)。
^
是 1.[any].[any](最新的次要版本)
~
是 1.2.[any](最新的补丁)
this blog post 了解 semver 如何应用于 npm
以及他们为使其匹配所做的工作the semver standard
http://blog.npmjs.org/post/98131109725/npm-2-0-0
〜波浪号:
~ 冻结主要和次要数字。
当您准备好接受依赖项中的错误修复但不想要任何潜在的不兼容更改时使用它。
波浪号匹配最新的次要版本(中间数字)。
~1.2.3 将匹配所有 1.2.x 版本,但会错过 1.3.0。
波浪号 (~) 为您提供错误修复版本
插入符号:
^ 仅冻结主号码。
当您密切关注您的依赖关系并准备好在次要版本不兼容时快速更改代码时使用它。
它会将您更新到最新的主要版本(第一个数字)。
^1.2.3 将匹配包括 1.3.0 在内的任何 1.xx 版本,但在 2.0.0 上会延迟。
插入符号 (^) 还为您提供向后兼容的新功能。
帽子匹配可能被视为“损坏”,因为它不会将 ^0.1.2
更新为 0.2.0
。当软件出现时,使用 0.x.y
版本,帽子匹配将只匹配最后一个变化的数字 (y
)。这是故意的。原因是在软件不断发展的同时,API 也在迅速变化:前一天你有这些方法,前几天你有了这些方法,而旧的方法已经消失了。如果您不想破坏已经在使用您的库的人的代码,您可以增加主要版本:例如 1.0.0
-> 2.0.0
-> 3.0.0
。因此,当您的软件最终 100% 完成并功能齐全时,它会像版本 11.0.0
一样,看起来没有多大意义,实际上看起来很混乱。另一方面,如果您使用 0.1.x
-> 0.2.x
-> 0.3.x
版本,然后当软件最终 100% 完成并功能齐全时,它作为版本 1.0.0
发布,这意味着“此版本是一项长期服务,您可以继续使用此版本的你的生产代码中的库,作者明天或下个月不会改变一切,他也不会放弃这个包”。
规则是:在您的软件尚未成熟时使用 0.x.y
版本控制,并在您的公共 API 更改时增加中间数字来发布它(因此拥有 ^0.1.0
的人不会获得 0.2.0
更新,也不会破坏他们的代码)。然后,当软件成熟时,在 1.0.0
下发布它,并在每次公共 API 更改时增加最左边的数字(因此拥有 ^1.0.0
的人不会获得 2.0.0
更新,也不会破坏他们的代码)。
Given a version number MAJOR.MINOR.PATCH, increment the:
MAJOR version when you make incompatible API changes,
MINOR version when you add functionality in a backwards-compatible manner, and
PATCH version when you make backwards-compatible bug fixes.
caret ^
包括大于同一主要范围内的特定版本的所有内容。
波浪号 ~
包括所有大于同一次要范围内的特定版本的内容。
例如,要指定最高 1.0.4 的可接受版本范围,请使用以下语法:
补丁版本:1.0 或 1.0.x 或 ~1.0.4
次要版本:1 或 1.x 或 ^1.0.4
主要版本:* 或 x
有关语义版本控制语法的更多信息,请参阅 npm semver calculator。
https://i.stack.imgur.com/7EyGM.png
更多来自 npm 文档 About semantic versioning
一班轮解释
标准版本控制系统是major.minor.build(例如2.4.1)
npm 根据这些字符检查并修复特定包的版本
:主要版本是固定的,次要版本是固定的,匹配任何内部版本号
例如:~2.4.1 意味着它将检查 2.4.x 其中 x 是什么
: 主要版本是固定的,匹配任何次要版本,匹配任何内部版本号
例如:^2.4.1 表示它将检查 2.xx 其中 x 是什么
波浪号 ~ 匹配次要版本,如果您安装了具有 1.4.2 的软件包,并且在安装后,如果在您的 package.json 中将其用作 ~1.4.2 然后 npm install ,则版本 1.4.3 和 1.4.4 也可用在您的项目中升级后将在您的项目中安装 1.4.4。但是该软件包有 1.5.0 可用,那么它不会被 ~ 安装。它被称为次要版本。
Caret ^ 匹配主要版本,如果您的项目中安装了 1.4.2 包,并且在您的安装 1.5.0 发布后,那么 ^ 将安装主要版本。如果您有 ^1.4.2,它将不允许安装 2.1.0。
固定版本如果您不想在每次安装时更改软件包的版本,则使用不带任何特殊字符的固定版本,例如“1.4.2”
最新版本 * 如果要安装最新版本,则仅在包名称前使用 *。
您可能已经在 package.json 中看到了波浪号 (~) 和插入符号 (^)。它们之间有什么区别?
当您执行 npm install moment --save 时,它会使用插入符号 (^) 前缀保存 package.json 中的条目。
波浪号 (~)
用最简单的术语来说,波浪号 (~) 匹配最新的次要版本(中间数字)。 ~1.2.3 将匹配所有 1.2.x 版本,但会错过 1.3.0。
插入符号 (^)
另一方面,插入符号 (^) 更轻松。它会将您更新到最新的主要版本(第一个数字)。 ^1.2.3 将匹配任何 1.xx 版本,包括 1.3.0,但将推迟到 2.0.0。
参考:https://medium.com/@Hardy2151/caret-and-tilde-in-package-json-57f1cbbe347b
波浪号 (~)
主要版本是固定的,次要版本是固定的,匹配任何内部版本号
"express": "~4.13.3"
~4.13.3
表示它将检查 4.13.x 其中 x 是任何东西和 4.14.0
插入符号 (^)
主要版本是固定的,匹配任何次要版本,匹配任何内部版本号
"supertest": "^3.0.0"
^3.0.0
表示它将检查 3.xx 其中 x 是什么
semver 分为 3 个主要部分,由点分隔。
major.minor.patch
1.0.0
这些不同的主要、次要和补丁用于标识不同的版本。潮汐 (~) 和插入符号 (^) 用于标识要在包版本控制中使用的次要版本和补丁版本。
~1.0.1
Install 1.0.1 or **latest patch versions** such as 1.0.2 ,1.0.5
^1.0.1
Install 1.0.1 or **latest patch and minor versions** such as 1.0.2 ,1.1.0 ,1.1.1
与此问题相关,您可以查看 Composer documentation on versions,但简而言之:
波浪号版本范围 (~) - ~1.2.3 相当于 >=1.2.3 <1.3.0
插入符号版本范围 (^) - ~1.2.3 相当于 >=1.2.3 <2.0.0
因此,使用 Tilde 您将获得补丁的自动更新,但不会更新次要和主要版本。但是,如果您使用 Caret,您将获得补丁和次要版本,但您不会获得主要(重大更改)版本。
波浪号版本被认为是“更安全”的方法,但如果您使用可靠的依赖项(维护良好的库),您应该不会对 Caret 版本有任何问题(因为微小的更改不应该是破坏性更改。
您可能应该查看 this stackoverflow post about differences between composer install and composer update。
本身不是一个答案,而是一个似乎被忽视的观察结果。
插入符号范围的描述:
见:https://github.com/npm/node-semver#caret-ranges-123-025-004
允许不修改 [major, minor, patch] 元组中最左边的非零数字的更改。
表示 ^10.2.3
匹配 10.2.3 <= v < 20.0.0
我不认为那是他们的意思。引入 11.xx 到 19.xx 版本会破坏您的代码。
我认为他们的意思是left most non-zero number field
。 SemVer 中没有任何内容要求数字字段为一位数。
Allows changes that do not modify the left-most non-zero element
。
版本号在语法中指定具有不同含义的每个部分。语法分为三个部分,用点分隔。
主要.次要补丁 1.0.2
主要、次要和补丁代表一个包的不同版本。
npm 使用波浪号 (~) 和插入符号 (^) 分别指定要使用的补丁和次要版本。
因此,如果您看到 ~1.0.2,则表示安装版本 1.0.2 或最新的补丁版本,例如 1.0.4。如果您看到 ^1.0.2,则表示安装版本 1.0.2 或最新的次要版本或补丁版本,例如 1.1.0。
波浪号 ~
指定次要版本
插入符号 ^
指定主要版本发布
例如,如果软件包版本为 4.5.2
,则更新时:
~4.5.2
将安装最新的 4.5.x version (MINOR VERSION)
^4.5.2
将安装最新的 4.x.x version (MAJOR VERSION)
^
或~
的无意义的 npm。如果您想严格控制您的版本,请设置此项:npm config set save-prefix=''
0.2.x
时,@jgillich 在 semver 中,2
不是major version
。这就是 docs.npmjs.com 使用特定词的原因:the left-most non-zero digit
。这种情况又如何:^0.0.4 表示 0.0.4A
:0.0.1
、0.0.2
和0.0.3
。0.0.1
中有一个错误,因此您希望在您的包B
中至少包含0.0.2
。如果你写0.0.x
,你会得到0.0.3
,这没关系。但是,如果某些其他包C
同时需要B
和A
并且另外具有约束"A": "<0.0.2"
,您将获得0.0.1
而不会显示任何冲突问题,这不是您想要的。使用波浪号~0.0.2
应该可以帮助您避免此问题。