package.json中的tilde(〜)和caret(^)有什么区别?


3378

我已经升级到最新的稳定后nodenpm,我试过npm install moment --save。它将条目保存在package.json带有脱^字符号前缀的中。以前,它是一个波浪号~前缀。

  1. 为什么要进行这些更改npm
  2. tilde ~和caret有^什么区别?
  3. 与其他相比有什么优势?

42
仅供参考,您可以执行以下操作,以防止使用前缀或使用自定义前缀npm config set save-prefix=''。(~如果那是您喜欢的话,请在引号中粘贴。)我亲自执行此操作,并包装生产中的东西。
fncomp

19
关于波浪号和插入符号的工作方式的所有细节,以及差异:github.com/npm/node-semver#tilde-ranges-123-12-1
Jeffrey Martinez,

11
此工具是测试semver.npmjs.com
chaiyachaiya

@fncomp只是想澄清我是否对您的评论正确..您在项目中仅使用特定版本的依赖项吗?我们的团队对升级依赖项犹豫不决。.您是否建议对依赖项使用特定版本或前缀“〜”?
blogs4t

@fncomp您能否说“我个人这样做并包装生产中的东西”来详细说明您的意思。谢谢!
blogs4t

Answers:


3836

请参阅NPM文档semver文档

〜version“大约等同于版本”将把您更新到所有将来的补丁程序版本,而不会增加次要版本。~1.2.3将使用从1.2.3到<1.3.0的发行版。

^ version“与版本兼容”将在不增加主要版本的情况下将您更新为所有将来的次要/修补程序版本。^2.3.4将使用从2.3.4到<3.0.0的发行版。

请参阅下面的评论。


323
在此处发布以希望抓住那些不太了解这一点的人,但是^和〜都假定您可以信任依赖项中的次要版本和点发布。如果您正在发布图书馆并希望其他人信任您,请不要盲目接受下游需求。从依赖性中释放出不良的点可能会在上游引起连锁反应,并且当事情变成梨形时,人们会敲门。这是在生产代码上使用npm收缩包装的另一个重要原因。
tehfoo 2015年

8
您也可以取消npm的所有废话,在版本之前加上a ^或a ~。如果您想对版本进行严格控制,请设置此选项: npm config set save-prefix=''
kumarharsh 2015年

5
@prasanthv是正确的:来自docs.npmjs.com/misc/semver#caret-ranges-1-2-3-0-2-5-0-0-4:插入符范围^ 1.2.3 ^ 0.2.5 ^ 0.0 .4。允许所做的更改不会修改[major,minor,patch]元组中最左边的非零数字。换句话说,这允许对1.0.0及更高版本的补丁程序和次要更新,对于0.X> = 0.1.0版本的补丁程序更新以及对0.0.X版本的更新。
rofrol 2015年

15
@jgillich在semver当你使用0.2.x2是不是major version。这就是docs.npmjs.com使用特定词的原因the left-most non-zero digit。同样关于这种情况:^ 0.0.4表示0.0.4
rofrol

11
@FagnerBrack:您提供的特定示例是正确的,但是通常您的思维方式是错误的。举个例子:假设你有包装A在3个版本:0.0.10.0.20.0.3。有个bug,0.0.1因此您至少0.0.2要包装在包装中B。如果您编写0.0.x,将得到0.0.3,这是确定的。但是,如果某些其他软件包同时C需要BA并具有约束,"A": "<0.0.2"那么您将0.0.1不会显示任何冲突问题,而这不是您想要的。使用波浪号~0.0.2应该可以帮助您避免此问题。
Maciej Sz 2015年

861

我还想添加官方的npmjs文档,其中描述了所有针对版本特定性的方法,包括问题中提到的方法-

https://docs.npmjs.com/files/package.json

https://docs.npmjs.com/misc/semver#x-ranges-12x-1x-12-

  • ~version“大约等同于版本”,请参见npm semver-Tilde Rangessemver(7)
  • ^version“与版本兼容”请参阅npm semver-插入符号范围semver(7)
  • version 必须完全匹配版本
  • >version 必须大于版本
  • >=version 等等
  • <version
  • <=version
  • 1.2.x 1.2.0、1.2.1等,但不是1.3.0
  • http://sometarballurl (这可能是将在本地下载并安装的tarball的URL
  • * 匹配任何版本
  • latest 获取最新版本

上面的列表并不详尽。其他版本说明符包括GitHub网址和GitHub用户仓库,本地路径以及带有特定npm标签的软件包


8
也可以指定确切的版本范围,例如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及以下。
CodeManX


"Approximately equivalent to version"并且"Compatible with version"是描述〜和^行为的令人沮丧的非特定方式。感谢@jgillich提供实际答案!
斯科特·斯塔福德,

635

npm允许安装比指定版本更新的软件包。使用代字号(~)可为您提供错误修复版本,而插入符号(^)也可为您提供向后兼容的新功能。

问题在于旧版本通常不会收到太多的错误修复,因此npm使用caret(^)作为默认值--save

semver表

根据:“ Semver解释了-为什么我的package.json中有插入符号(^)?”

请注意,规则适用于1.0.0以上的版本,并非每个项目都遵循语义版本控制。对于版本0.xx,插入记号仅允许更新修补程序,即,其行为与代字号相同。请参阅“范围”

这是概念的直观说明:

semver图

来源:“语义版本控制速查表”


2
那^ 0.2.5呢?来自docs.npmjs.com/misc/semver#caret-ranges-1-2-3-0-2-5-0-0-4:插入符范围^ 1.2.3 ^ 0.2.5 ^ 0.0.4。允许所做的更改不会修改[major,minor,patch]元组中最左边的非零数字。换句话说,这允许对1.0.0及更高版本的补丁程序和次要更新,对于0.X> = 0.1.0版本的补丁程序更新以及对0.0.X版本的更新。
rofrol 2015年

11
@rofrol 1.0.0之前的任何版本都被认为是不稳定的,并且这些规则不适用
pspi 2015年

2
所以您的解释还不完整
rofrol

5
@rofrol是的,有时省略可读性是好的,因为软件包json中的依赖项低于1.0.0的可能性很小。另请参见20/80原理,这是专注于重要事项的好规则
pspi 2015年

1
@pspi 1.0.0以下的版本是“不太可能”吗?在60位中,我们有15位左右,而且大多数都不是晦涩的。
戴夫牛顿

99

森弗

<major>.<minor>.<patch>-beta.<beta> == 1.2.3-beta.2
  • 使用npm semver计算器进行测试。(尽管对^(包括在相同主范围内大于特定版本的所有内容)和〜(包括在相同主范围内大于特定版本的所有内容)的解释不是100%正确,但计算器似乎可以正常工作)
  • 另外,也可以改用SemVer Check,它不需要您选择软件包,还提供了说明。

允许或禁止更改

  • 引脚版本:1.2.3
  • 使用^(如头部)。允许从左侧的第二个非零级别进行更新:^0.2.3Means 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
  • Ommit最右边的级别:0.2手段0.2 <= v < 1。不同于~因为:
    • 始终从开始省略级别版本开始 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

注意:缺少主要,次要,补丁或beta没有编号的指定any与缺少级别相同。

注意:当您安装具有0主要级别的软件包时,此更新将仅安装新的beta / pr级别版本!那是因为在中npm设置^为默认值,package.json并且当安装的版本是时0.1.3,它会冻结所有主要/次要/补丁程序级别。


告诉人们避免从0开始项目,因为图书馆和普通开发人员不了解系统是一个糟糕的解决方案。我认为@asdfasdfads具有更好的信息。
ProLoser

@ProLoser我只是认为应该简化系统,我们不应该使用0.x版本。
rofrol

1
有关早期生命周期开发和v0的用例非常有意义。学习v0的正常运行方式实际上使我期待其他早期生命周期项目。这意味着您可以拥有一个快速变化的API,并且具有很多向后不兼容的功能,而不必在实际上并非如此的情况下强行将您的项目声明为1.x(又称稳定)。
ProLoser

我了解这一点,但我只是不喜欢它与semver和qualifier一起使用的方式
rofrol 2016年

2
感觉更像是一种意见,不应被视为一种普遍接受的方法。^ 0.1.x可以完美地获得补丁。
ProLoser

93

~修正主要和次要数字。当您准备接受依赖项中的错误修复但不希望任何潜在的不兼容更改时,可以使用它。

^仅固定主号码。当您密切关注依赖关系并准备好在次要版本不兼容时准备快速更改代码时,可以使用它。

除此之外,^不支持由旧版本的NPM,并应谨慎使用。

因此,这^是一个很好的默认值,但不是完美的。我建议仔细选择和配置对您最有用的semver运算符。


13
不正确:插入符号范围^ 1.2.3 ^ 0.2.5 ^ 0.0.4。允许所做的更改不会修改[major,minor,patch]元组中最左边的非零数字。换句话说,这允许对1.0.0及更高版本的补丁程序和次要更新,对于0.X> = 0.1.0版本的补丁程序更新以及对0.0.X版本的更新。docs.npmjs.com/misc/semver#caret-ranges-1-2-3-0-2-5-0-0-4
rofrol 2015年

6
这个答案是完全错误的(这里还有许多其他答案)。这些都没有解决一个大数字!就像@rofrol所说的,^只是保持最左边的非零数字不变。另一方面,〜如果仅指定次要版本(例如〜1.2.3或〜1.2),则仅允许补丁更新;而如果未指定次要版本(例如〜1),则仅允许次要更新。
TheBaj

2
@TheBaj它们的意思是将“ fix”定义为“ define”(“ fixate”),而不是“ adjust”,因此大家都同意如何处理主号码。
maaartinus

1
是的,这个答案似乎完全是倒退,直到我意识到应答者的意思是“固定”,就像“使固定,固定或不变”一样。
NattyC

57

~:合理接近

   ~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

17
@kytwb-不 在零发行版本号的特殊情况下,克拉与波浪号等效。因此,即使是很小的增量,也^0.1.3只接受版本0.1.x,而不会接受0.2.0。此行为等效于~0.1.3。出现这种现象的原因是由于零发布软件包仍然被认为是不稳定的。用semver.org#4 的话来说,“任何内容都可能随时更改”(包括向后不兼容的更改)。
chharvey 2015年

31

^是1. [any]。[any](最新的次要版本)
~是1.2。[any](最新的补丁)

一个伟大的读取是这个博客帖子上semver如何适用于NPM
和他们在做什么,使之匹配的semver标准
http://blog.npmjs.org/post/98131109725/npm-2-0-0


2
不正确:插入符号范围^ 1.2.3 ^ 0.2.5 ^ 0.0.4。允许所做的更改不会修改[major,minor,patch]元组中最左边的非零数字。换句话说,这允许对1.0.0及更高版本的补丁程序和次要更新,对于0.X> = 0.1.0版本的补丁程序更新以及对0.0.X版本的更新。docs.npmjs.com/misc/semver#caret-ranges-1-2-3-0-2-5-0-0-4
rofrol 2015年

28

帽子匹配可能会被认为“已损坏”,因为它不会更新^0.1.20.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.

此评论非常有用,并且没有很好地记录在案。您是否有有关此行为的文档链接?关于v0项目的答案对我有很大帮助。
ProLoser

我没有链接:我通过谷歌搜索和使用npm语义版本计算器semver.npmjs.com
catamphetamine

2
需要以更正式的方式添加到他们的文档中。我在Sony与工程团队进行了一次演讲,因为它似乎很容易被忽略。slides.com/proloser/semver-v0
ProLoser

24

〜蒂尔德:

  • ~冻结主要和次要数字。
  • 当您准备接受依赖项中的错误修复但不希望任何潜在的不兼容更改时,可以使用它。
  • 代字号与最新的次要版本(中间编号)匹配。
  • 〜1.2.3将与所有1.2.x版本匹配,但将错过1.3.0。
  • Tilde(〜)为您提供错误修复版本

^脱字号:

  • ^ 仅冻结主号码。
  • 当您密切关注依赖关系并准备好在次要版本不兼容时准备快速更改代码时,可以使用它。
  • 它将把您更新到最新的主要版本(第一个数字)。
  • ^ 1.2.3将与任何1.xx版本(包括1.3.0)匹配,但将在2.0.0上生效。
  • 脱字号(^)也为您提供了向后兼容的新功能。

1
代字号与最新的修补程序版本(最后一个数字)匹配。插入符与最新的次要版本(中间编号)匹配。
阿卜杜勒·劳夫

“冻结”是最好的解释。
mhrabiee

插入符号既冻结主号码,又会更新到最新的主版本(第一个号码)?主要数字是第一个数字,因此这没有意义。
NattyC

19

Tilde〜匹配次要版本,如果您安装了具有1.4.2的软件包,并且在安装后,如果在package.json中将其用作〜1.4.2,则还可以使用版本1.4.3和1.4.4,然后npm install在升级后的项目中将在项目中安装1.4.4。但是该软件包有1.5.0可用,因此〜不会安装。它称为次要版本。

插入符^匹配主要版本,如果在项目中安装了1.4.2软件包,并且在发布1.5.0版本之后,则^将安装主要版本。如果您具有^ 1.4.2,则将不允许安装2.1.0 。

固定版本,如果您不想在每次安装时都更改软件包的版本,则使用不带任何特殊字符的固定版本,例如“ 1.4.2”

最新版本*如果要安装最新版本,则仅在软件包名称前使用*。


3
这个答案是误导的。SemVer明确指出,正常版本号必须采用XYZ格式[其中] X是主要版本,Y是次要版本,Z是补丁版本。
狮子座

15

一班班轮说明

标准版本控制系统是major.minor.build(例如2.4.1)

npm根据这些字符检查并修复特定软件包的版本

:主版本是固定的,次版本是固定的,匹配任何内部版本号

例如:〜2.4.1表示它将检查2.4.x,其中x为任意值

^:主要版本是固定的,与任何次要版本匹配,与任何内部版本号匹配

例如:^ 2.4.1表示它将检查2.xx,其中x为任意值


5
我在此答案中看到7行
FluxLemur

11

您可能已经在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


同样,这个答案是误导性的。SemVer明确指出,正常版本号必须采用XYZ格式[其中] X是主要版本,Y是次要版本,Z是补丁版本。
狮子座

5

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

4

提尔德(〜)

主要版本是固定的,次要版本是固定的,匹配任何内部版本号

"express": "~4.13.3" 

~4.13.3 表示它将检查4.13.x,其中x为任意值和4.14.0

脱字号(^)

主要版本是固定的,匹配任何次要版本,匹配任何内部版本号

"supertest": "^3.0.0"

^3.0.0 表示它将检查3.xx,其中x为任意值


您能否详细说明此答案与4年前发布的相同答案有何不同?
富兰克林·于

2

版本号采用的语法表示每个部分的含义不同。语法分为三部分,用点分隔。

major.minor.patch 1.0.2

主要,次要和补丁表示软件包的不同发行版。

npm使用代字号(〜)和脱字符号(^)分别指定要使用的补丁程序和次要版本。

因此,如果看到〜1.0.2,则意味着安装版本1.0.2或最新的修补程序版本(例如1.0.4)。如果看到^ 1.0.2,则意味着安装版本1.0.2或最新的次要版本或修补程序版本(例如1.1.0)。


1
您能否详细说明此答案与4年前发布的相同答案有何不同?
富兰克林·于

2

克拉 ^包括相同主要范围内比特定版本更大的所有物品。

代字号 ~在相同的次要范围内包含大于特定版本的所有内容。

例如,要指定可接受的最高版本范围为1.0.4,请使用以下语法:

  • 修补程序版本:1.0或1.0.x或〜1.0.4
  • 次要版本:1或1.x或^ 1.0.4
  • 主要版本:*或x

有关语义版本语法的更多信息,请参见npm semver计算器

已发布软件包中的npm语义版本

npm文档中的更多内容关于语义版本控制


1

本质上,这不是一个答案,但似乎被忽略了。

克拉范围的说明:

参见: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中没有要求数字字段为一位数字的内容。


0

〜特定于次要版本^指定主要版本

例如,如果软件包版本为4.5.2,则在更新〜4.5.2时将安装最新的4.5.x版本(主版本)^ 4.5.2将安装最新的4.xx版本(主版本)


8
您能否详细说明此答案与4年前发布的相同答案有何不同?
富兰克林于

0

与此问题相关,您可以查看有关版本的Composer文档,但简而言之:

  • 波形版本范围()-〜1.2.3等于> = 1.2.3 < 1.3.0
  • 脱字号版本范围(^)-〜1.2.3等于> = 1.2.3 < 2.0.0

因此,使用Tilde,您将获得补丁程序的自动更新,但次要和主要版本将不会更新。但是,如果使用Caret,则将获得补丁程序和次要版本,但不会获得主版本(重大更改)。

Tilde版本被认为是“更安全”的方法,但是,如果您使用可靠的依赖项(维护良好的库),则Caret版本应该不会有任何问题(因为较小的更改不应破坏更改)。

您可能应该查看此stackoverflow帖子,了解composer安装和composer更新之间的区别

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.