题 package.json中的tilde(〜)和插入符号(^)有什么区别?


我升级到最新稳定后 node 和 npm, 我试过了 npm install moment --save。它保存了条目 package.json 随着 caret(^) 字首。以前,它是一个 tilde(~) 字首。

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

2249
2018-03-12 06:02


起源


仅供参考,您可以通过以下方式阻止前缀或使用自定义前缀: npm config set save-prefix=''。 (棒 ~ 在引号中,如果你喜欢这个。)我个人这样做,并收缩生产中的东西。 - fncomp
关于波浪和插入符号工作和差异的所有细节: github.com/npm/node-semver#tilde-ranges-123-12-1 - Jeffrey Martinez
这个工具是测试的好帮手 semver.npmjs.com - chaiyachaiya
@fncomp只想澄清我的评论是否正确..你是否只在项目中使用特定版本的依赖项?我们的团队对升级依赖项犹豫不决..你会建议使用特定版本或依赖项的'〜'前缀..? - blogs4t
@fncomp你可以通过说“我个人这样做并收缩生产中的东西”来详细说明你的意思。谢谢! - blogs4t


答案:


用最简单的术语来说,代字号与最新的次要版本相匹配   (中间数字)。 ~1.2.3将匹配所有1.2.x版本,但会   错过1.3.0。

另一方面,插入符号更放松。它会更新你   最新的主要版本(第一个数字)。 ^ 1.2.3将匹配   任何1.x.x版本,包括1.3.0,但将在2.0.0推迟。

http://fredkschott.com/post/2014/02/npm-no-longer-defaults-to-tildes/


2640
2018-03-12 08:28



发布在这里希望能够抓住那些不太认真的人,但是^和〜都假设你可以信任来自你的依赖项的次要和点发布。如果您要发布图书馆并希望其他人信任您,请不要盲目接受DOWNSTREAM DEPENDENCIES。从你的依赖中释放一个坏点可能会导致上游的连锁反应,并且当事情变成梨形时会让人敲门。这是在生产代码上使用npm shrinkwrap的另一个重要原因。 - tehfoo
这是误导 ^。它说 ^  会将您更新到最新版本 重大的 版,实际上它会将您更新为最新版本 次要 版。即: - ^ 1.2.3:=> = 1.2.3 <2.0.0 - ^ 0.2.3:=> = 0.2.3 <0.3.0 - ^ 0.0.3:=> = 0.0.3 <0.0.4 - prasanthv
当你使用时,@ jgillich在semver 0.2.x, 2 不是 major version。这就是为什么 docs.npmjs.com 使用了具体的词: the left-most non-zero digit。那么这个案例呢:^ 0.0.4表示0.0.4 - rofrol
@FagnerBrack:您提供的具体示例是正确的,但通常您的思维方式是错误的。一个例子:假设你有包裹 A 有3个版本: 0.0.1, 0.0.2 和 0.0.3。有一个错误 0.0.1 所以你想要至少拥有 0.0.2 在你的包裹中 B。如果你写 0.0.x 你会得到 0.0.3,这没关系。但如果其他一些包 C 需要两者 B 和 A 另外还有约束力 "A": "<0.0.2" 你会得到 0.0.1 没有显示任何冲突问题,这不是你想要的。使用代字号 ~0.0.2 应该可以帮助您避免这个问题。 - Maciej Sz
很奇怪,这个错误的答案 It will update you to the most recent major version 有2k + upvotes。我想知道有多少人现在这么认为 ^ 更新主要版本!! semserv版本控制中的major / minor / patch意味着没有任何歧义 - 它只是错误的 - Drenai


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

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

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

  • ~version “大致相当于版本”见 npm semver - Tilde Ranges & semver(7)
  • ^version “与版本兼容”请参阅 npm semver - Caret Ranges & 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标记的包


571
2017-09-16 06:25



也可以指定确切的版本范围,例如 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
@CoDEmanX如果使用,为什么包含1.3.0 <? - Janus Troelsen
我的坏,应该读 <=1.3.0。 - CoDEmanX
1.x.x可能吗? - Venryx
@Venryx是的。这将是所有版本> = 1.0.0和<2.0.0 - Ahmad


Npm允许安装比指定版本更新的软件包版本。使用代字号(~)给你bug修复版本和插入符号(^)为您提供向后兼容的新功能。

问题是旧版本通常不会收到很多bug修复,所以npm使用插入符号(^)作为默认值 --save

semver table

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

注意 规则适用于1.0.0以上的版本,并非每个项目都遵循语义版本。对于版本0.x.x,插入符号仅允许 补丁 更新,即它的行为与波形符相同。看到 “Caret Ranges”

以下是概念的直观解释:

semver diagram

资源: “语义版本Cheatsheet”


349
2017-07-30 20:40



^ 0.2.5怎么样?从 docs.npmjs.com/misc/semver#caret-ranges-1-2-3-0-2-5-0-0-4:Caret Ranges ^ 1.2.3 ^ 0.2.5 ^ 0.0.4。允许更改不会修改[major,minor,patch]元组中最左边的非零数字。换句话说,这允许版本1.0.0及更高版本的补丁和次要更新,版本0.X> = 0.1.0的补丁更新,以及版本0.0.X的更新。 - rofrol
@rofrol 1.0.0之前的任何版本都被认为是不稳定的,这些规则不适用 - pspi
所以你的解释并不完整 - rofrol
@rofrol是的,有时候省略了可读性,对于包json中的依赖性而言,任何低于1.0.0的可能性都很低。另见20/80原则,关注重点是一个很好的规则 - pspi
看到我的回答。你怎么看? stackoverflow.com/questions/22343224/... - rofrol


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

^ 仅修复主要数字。当您密切关注您的依赖关系时,它会被使用,并且如果次要版本不兼容,您可以快速更改代码。

在此之上, ^ 是 不支持 旧的npm版本,应谨慎使用。

所以, ^ 是一个很好的默认,但它并不完美。我建议您仔细挑选并配置对您最有用的semver运算符。


74
2018-03-12 23:05



不正确:Caret Ranges ^ 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
这个答案是完全错误的(和其他许多人一样)。这些都没有确定一个主要数字!正如@rofrol所说,^只是保持最左边的非零数字不变。另一方面,如果指定次要版本(例如~1.2.3或~1.2),则仅允许补丁更新,并且如果未指定次要版本(例如~1)则允许次要更新。 - TheBaj
@TheBaj他们的意思是“修复”为“定义”(“固定”)而不是“调整”,所以你们都同意如何处理主要数字。 - maaartinus


Semver

<major>.<minor>.<patch>-beta.<beta> == 1.2.3-beta.2
  • 使用 npm semver计算器 供测试用。 (虽然对^的解释(包括在同一主要范围内的特定版本以外的所有内容)和〜(包括在同一次要范围内的特定版本以外的所有内容)都不是100%正确,但计算器似乎工作正常)
  • 或者,使用 SemVer检查 相反,这不需要你选择一个包,也提供解释。

允许或禁止更改

  • 针版: 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
    • 您可以设置起始主要版本而无需指定子级别。

所有(希望)可能性

设置启动主要级别并允许更新

*  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,它会冻结所有主要/次要/补丁级别。


66
2017-10-11 16:52



告诉人们避免从0开始项目,因为库和消费开发人员不了解系统是一个糟糕的解决方案。我认为@asdfasdfads有更好的信息。 - ProLoser
@ProLoser我只是认为系统应该简化,我们不应该使用0.x版本。 - rofrol
早期生命周期开发和v0的使用案例很有意义。了解v0如何正常运行实际上让我期待其他早期生命周期项目。这意味着你可以拥有一个快速变化的API,它具有很多向后不兼容的特性,而不会被迫将你的项目声明为1.x(又名:stable)。 - ProLoser
我理解它,但我不喜欢它与semver和限定符一起使用的方式 - rofrol
这感觉更像是一种观点,不应该被视为一种普遍接受的方法。并且^ 0.1.x完全可以获得补丁。 - ProLoser


~ :合理  至

   ~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

42
2018-06-27 16:12



^0.1.3: 0.1.3 <= accepted < 1.0.0 相反,不是吗? - kytwb
@kytwb - 没有。在第0版发布版本号的特殊情况下,克拉相当于波浪号。从而 ^0.1.3 只接受版本 0.1.x 并且不会接受 0.2.0,即使这是一个小的增量。这种行为相当于 ~0.1.3。这种行为背后的原因是由于零发布包仍然被认为是不稳定的;用的话 semver.org,#4,“任何时候都可能发生变化”(包括向后不兼容的变化)。 - chharvey


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

21
2017-10-19 11:24



这个评论非常有用,似乎没有很好的记录。您是否有关于此行为的文档的链接?关于v0项目的答案对我帮助很大。 - ProLoser
我没有链接:我通过谷歌搜索和使用npm语义版本计算器找到了这些信息 semver.npmjs.com - asdfasdfads
需要以更正式的方式添加到他们的文档中。我在索尼向我的工程团队发表演讲,因为它似乎很容易被忽视。 slides.com/proloser/semver-v0 - ProLoser


^ 是1. [any]。[any](最新的小版本)
~ 是1.2。[任何](最新补丁)

很棒的阅读 这篇博文 关于semver如何适用于npm
他们正在做些什么使它匹配 semver标准
http://blog.npmjs.org/post/98131109725/npm-2-0-0


20
2017-12-15 18:07



不正确:Caret Ranges ^ 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


一个班轮解释

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

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

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

例如:~2.4.1表示它将检查2.4.x,其中x是任何东西

^ :主要版本已修复,匹配任何次要版本,匹配任何内部版本号

例如:^ 2.4.1表示它将检查2.x.x,其中x是任何东西


8
2018-01-21 08:00



我在这个答案中看到7行 - FluxLemur


〜蒂尔德:

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

^插入符号:

  • ^ 仅修复主要数字。
  • 当您密切关注您的依赖关系时,它会被使用,并且如果次要版本不兼容,您可以快速更改代码。
  • 它会更新你的 最新的主要版本 (第一个数字)。
  • ^ 1.2.3将匹配包括1.3.0在内的任何1.x.x版本,但它将在2.0.0上推迟。
  • Caret(^)也为您提供向后兼容的新功能。

3
2017-09-30 10:56



代字号匹配最新的修补程序版本(最后一个数字)。插入符号匹配最新的次要版本(中间数字)。 - Abdul Rauf


Tilde(〜)

主要版本是固定的,次要版本是固定的,匹配任何版本   数

"express": "~4.13.3" 

~4.13.3 意味着它将检查4.13.x,其中x是任何东西,4.14.0

插入符号(^) 

主要版本是固定的,匹配任何次要版本,匹配任何构建   数

"supertest": "^3.0.0"

^3.0.0 意味着它将检查3.x.x,其中x是任何东西


2
2018-03-09 12:21