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

Fiz*_*han 3111 node.js npm semantic-versioning package.json

我已经升级到最新的稳定后nodenpm,我试过npm install moment --save.它package.json使用^前缀保存条目.以前,它是一个~前缀.

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

jgi*_*ich 3554

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

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

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

请注意,作者的术语有些误导:当他说"最近的次要版本"时,他的意思是" 指定次要版本中最新的补丁版本".类似地,对于^,"最新的主要版本"应该被理解为" 指定主要版本中的最新次要版本".

  • 发布在这里希望能够抓住那些不太认真的人,但是^和〜都假设你可以信任来自你的依赖项的次要和点发布.如果您要发布图书馆并希望其他人信任您,请不要盲目接受DOWNSTREAM依赖.从你的依赖中释放一个坏点可能会导致上游的连锁反应,并且当事情变成梨形时会让人敲门.这是在生产代码中使用npm shrinkwrap的另一个重要原因. (285认同)
  • 这对'^`有误导作用.它说`^`_会将你更新到最近的**主**版本_,实际上它会将你更新为最新的**minor**版本.即: - ^ 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 (276认同)
  • 当你使用`0.2.x`时,@ jgillich在semver中,`2`不是'主要版本'.这就是为什么https://docs.npmjs.com使用了特定的词:`最左边的非零数字'.这个案例也是如此:^ 0.0.4表示0.0.4 (15认同)
  • @FagnerBrack:您提供的具体示例是正确的,但通常您的思维方式是错误的.一个例子:假设你有3个版本的包'A`:`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`可以帮助您避免此问题. (9认同)
  • 你也可以在你的版本之前用`^`或`~`来消除npm的所有废话.如果你想严格控制你的版本,请设置这个:`npm config set save-prefix =''` (5认同)
  • @prasanthv是对的:来自https://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的更新. (5认同)
  • @FagnerBrack:我说在使用代字号时你可以定义最小版本号(最低版本号).使用"0.0.x"表示法,您没有该选项,因为**任何**最低有效版本号都是有效的. (5认同)
  • 注意到最新的轻微,而不是主要.它是`Major`,`Minor`,`Patch`,`Hotfix`. (3认同)
  • 我编辑了这个答案以纠正解释.请不要在评论中抱怨错误的答案,请下次再去做! (2认同)

Ahm*_*mad 792

我想添加官方的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标记的包

  • 也可以指定确切的版本范围,例如`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和下面. (7认同)
  • “大约相当于版本”和“与版本兼容”是描述 ~ 和 ^ 行为的非常令人沮丧的非特定方式。感谢@jgillich 提供了实际的答案! (4认同)
  • 我很糟糕,应该读取为&lt;= 1.3.0`。 (2认同)
  • @Venryx是的.这将是所有版本> = 1.0.0和<2.0.0 (2认同)
  • @Simon_Weaver 在这种情况下,补丁版本为“0”,是的,它们是等效的。但是,例如,如果您有“~1.2.3”,则相当于“&gt;=1.2.3 &lt;1.3.0”,而“1.2.x”相当于“&gt;=1.2.0 &lt;1.3.0” ` --- 本质上,`~` 表示_任何大于或等于指定版本的补丁版本_,而该位置的 `x` 表示_任何数字_。完整语法在这里定义:https://github.com/npm/node-semver#advanced-range-syntax (2认同)

psp*_*spi 545

Npm允许安装比指定版本更新的软件包版本.使用tilde(~)为您提供错误修复版本,而caret(^)也为您提供向后兼容的新功能.

问题是旧版本通常不会收到太多错误修复,所以npm使用caret(^)作为默认值--save.

semver表

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

请注意,规则适用于1.0.0以上的版本,并非每个项目都遵循语义版本.对于0.xx版本,插入符号仅允许修补程序更新,即它的行为与代字号相同.见"Caret Ranges"

这是对概念的直观解释:

semver图

资料来源:"Semantic Versioning Cheatsheet".

  • @rofrol 1.0.0之前的任何版本都被认为是不稳定的,这些规则不适用 (9认同)
  • @pspi 版本低于 1.0.0 是“不太可能”吗?在 60 个中,我们有大约 15 个,其中大部分并不晦涩。 (6认同)
  • @rofrol是的,有时候省略了可读性,对于包json中的依赖性而言,任何低于1.0.0的可能性都很低.另见20/80原则,关注重点是一个很好的规则 (5认同)
  • 那^ 0.2.5呢?来自https://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&gt; = 0.1.0版本的补丁程序更新以及0.0.X版本的任何更新。 (2认同)
  • 所以你的解释并不完整 (2认同)

rof*_*rol 95

Semver

<major>.<minor>.<patch>-beta.<beta> == 1.2.3-beta.2
Run Code Online (Sandbox Code Playgroud)
  • 使用npm semver计算器进行测试.(虽然对^的解释(包括在同一主要范围内的特定版本以外的所有内容)和〜(包括在同一次要范围内的特定版本以外的所有内容)都不是100%正确,但计算器似乎工作正常)
  • 或者,使用SemVer Check代替,这不需要您选择包并提供解释.

允许或禁止更改

  • Pin版: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
Run Code Online (Sandbox Code Playgroud)

冻结主要级别

~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
Run Code Online (Sandbox Code Playgroud)

冻结小级别

^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
Run Code Online (Sandbox Code Playgroud)

冻结补丁级别

~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)
Run Code Online (Sandbox Code Playgroud)

禁止更新

1.2.3             1.2.3
^0.0.3 (0.0.3)    0.0.3
Run Code Online (Sandbox Code Playgroud)

注意:缺少主要,次要,补丁或指定beta没有数字,any与缺失的级别相同.

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

  • 围绕早期生命周期开发和 v0 的用例非常有意义。了解 v0 的正确行为实际上让我对其他早期生命周期项目充满了期待。这意味着您可以拥有一个快速变化且存在大量向后不兼容性的 API,而不必被迫将您的项目声明为 1.x(又名:稳定),而实际上它并非如此。 (2认同)
  • 这感觉更像是一种观点,不应该被视为一种普遍接受的方法.并且^ 0.1.x完全可以获得补丁. (2认同)

ale*_*lex 87

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

^仅修复主要数字.当您仔细观察您的依赖项并且准备好快速更改代码时,如果次要版本不兼容,则会使用它.

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

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

  • 不正确: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的更新.https://docs.npmjs.com/misc/semver#caret-ranges-1-2-3-0-2-5-0-0-4 (12认同)
  • 这个答案是完全错误的(和其他许多人一样).这些都没有确定一个主要数字!正如@rofrol所说,^只是保持最左边的非零数字不变.另一方面,如果指定了次要版本(例如~1.2.3或~1.2),则仅允许补丁更新;如果未指定次要版本(例如~1),则允许次要更新. (6认同)
  • @TheBaj 他们的意思是“修复”为“定义”(“固定”)而不是“调整”,所以你们都同意如何处理主要号码。 (3认同)

hao*_*ang 55

~:合理接近

   ~1.1.5: 1.1.0 <= accepted < 1.2.0
Run Code Online (Sandbox Code Playgroud)

^:兼容

   ^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
Run Code Online (Sandbox Code Playgroud)

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

Ela*_*ode 33

插入符 ^包括同一主要范围中大于特定版本的所有内容。

\n

波形符 ~包括同一次要范围内大于特定版本的所有内容。

\n

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

\n
    \n
  • 补丁版本:1.0 或 1.0.x 或 ~1.0.4
  • \n
  • 次要版本:1 或 1.x 或 ^1.0.4
  • \n
  • 主要版本:* 或 x
  • \n
\n

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

\n

已发布包\xc2\xa7 中的 npm 语义版本

\n

更多来自 npm 文档关于语义版本控制

\n


Wil*_*ern 29

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

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

  • 不正确: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的更新.https://docs.npmjs.com/misc/semver#caret-ranges-1-2-3-0-2-5-0-0-4 (2认同)

asd*_*ads 27

帽子匹配可以被认为是"破",因为它不会更新^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.
Run Code Online (Sandbox Code Playgroud)

  • 需要以更正式的方式添加到他们的文档中.我在索尼向我的工程团队发表演讲,因为它似乎很容易被忽视.http://slides.com/proloser/semver-v0 (2认同)

Lax*_*xmi 21

〜蒂尔德:

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

^插入:

  • ^ 仅修复主要数字.
  • 当您仔细观察您的依赖项并且准备好快速更改代码时,如果次要版本不兼容,则会使用它.
  • 它会将您更新为最新的主要版本(第一个数字).
  • ^ 1.2.3将匹配包括1.3.0在内的任何1.xx版本,但它将在2.0.0上推迟.
  • Caret(^)也为您提供向后兼容的新功能.

  • 波浪号与最新的补丁版本(最后一个数字)相匹配。插入符号匹配最新的次要版本(中间数字)。 (2认同)
  • @AbdulRauf是正确的。你的解释是错误的 (2认同)

Avi*_*ash 14

一个班轮解释

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

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

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

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

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

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

  • 我在这个答案中看到7行 (3认同)

Mud*_*sir 12

Tilde~匹配次要版本,如果你已经安装了1.4.2的软件包,安装后,如果在你的package.json中它也可以用作版本1.4.3和1.4.4,那么它将被用作~1.4.2然后npm install在升级后的项目中,将在项目中安装1.4.4.但是该软件包有1.5.0可用,然后它不会被〜安装.它被称为次要版本.

Caret ^匹配主要版本,如果你的项目停止1.4.2包,1.5.0也可用,那么^将安装主版本.如果你有^ 1.4.2,它将不允许安装2.1.0 .

固定版本,如果你不想在每次安装时更改软件包的版本,那么使用固定版本没有任何特殊字符,例如"1.4.2"

最新版本*如果您想安装最新版本,请仅在包名前面使用*.

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

小智 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


小智 7

semver 分为 3 个主要部分,由点分隔。

major.minor.patch
1.0.0
Run Code Online (Sandbox Code Playgroud)

这些不同的主要、次要和补丁用于标识不同的版本。潮汐 (~) 和插入符号 (^) 用于标识要在包版本控制中使用的次要版本和补丁版本。

~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
Run Code Online (Sandbox Code Playgroud)


mil*_*vic 6

与这个问题相关,您可以查看有关 versions 的 Composer 文档,但简而言之:

  • 波形符版本范围 ( ~ ) - ~1.2.3 相当于 >=1.2.3 < 1.3.0
  • 插入符号版本范围 ( ^ ) - ~1.2.3 相当于 >=1.2.3 < 2.0.0

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

波浪线版本被认为是“更安全”的方法,但是如果您使用可靠的依赖项(维护良好的库),那么插入符号版本不应该有任何问题(因为微小的更改不应该是重大更改。

您可能应该查看这篇关于 Composer install 和 Composer update 之间差异的 stackoverflow 帖子


Far*_*een 5

提尔德(〜)

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

"express": "~4.13.3" 
Run Code Online (Sandbox Code Playgroud)

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

脱字号(^)

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

"supertest": "^3.0.0"
Run Code Online (Sandbox Code Playgroud)

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

  • 您能否详细说明一下这个答案与[4年前发布的相同答案]有何不同(/sf/ask/1564025711/ Between-tilde-and-caret-in-package- json/22365742#22365742)? (2认同)

Jes*_*olm 5

这本身并不是一个答案,而是一个似乎被忽视的观察结果。

插入符号范围的描述:

请参阅: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 中没有任何内容要求数字字段为单位数。


Lea*_*iel 5

例如,对于:~1.8.0,您将匹配所有 1.8.x 版本,但您将丢失 1.9.0(这是默认行为)。

例如:^1.8.0 您将更新到最新的主要版本(第一期)。任何 1.xx 版本,包括 1.9.0,但与版本 2.0.0 保持距离

示例 3.9.2:

Symbol     Dependency   Versions    Changes
tilde (~)   ~3.9.2        3.9.*      -bug fix

caret (^)   ^3.9.2        3.*.*      -backwards compatible new functionality 
                                     -old functionality deprecated, but operational
                                     -large internal refactor
                                     -bug fix
Run Code Online (Sandbox Code Playgroud)