乐闻世界logo
搜索文章和话题

Package .json 中波浪号(~)和插入符号(^)有什么区别?

7 个月前提问
5 个月前修改
浏览次数123

6个答案

1
2
3
4
5
6

当您在package.json文件的依赖项列表中看到波浪号(~)和插入符号(^),这两个符号都是用来指定npm包的版本范围的。不过,它们指定的版本范围有所不同。

波浪号(~)

波浪号~后面的版本号意味着当您运行npm install时,npm会安装该版本号指定的小版本(minor version)中最新的补丁版本(patch version)。也就是说,它允许安装与指定版本在小版本号相同,但是补丁版本号更高的包。

例子:

如果package.json中的依赖项写为"library": "~1.2.3",那么安装的将是1.2.x的最新版本,x代表该小版本中的最新补丁。因此,如果最新版本是1.2.4,您将得到1.2.4。但是它不会安装1.3.0,因为这已经是下一个小版本了。

插入符号(^)

插入符号^后面的版本号意味着当您运行npm install时,npm会安装与指定的主版本号(major version)相同的最新版本,但允许小版本(minor version)和补丁版本(patch version)的变动。

例子:

如果package.json中的依赖项写为"library": "^1.2.3",那么安装的将是1.x.x的最新版本,只要它不是主版本号变更(比如到2.0.0),都是允许的。所以,如果存在1.3.0或者1.4.1这样的版本,使用^会允许安装这些版本。

总结

简而言之,插入符号^允许更宽泛的版本升级,适用于那些遵循语义化版本(semver)并且对小版本和补丁版本的更新只包含向后兼容的更改时。波浪号~则更加保守,只允许补丁级别的更新,适用于对版本更新更加谨慎的场景。

在实际开发中,选择使用哪个取决于对依赖包更新的控制需求以及对三方库的信任度。如果信任库的维护者遵循严格的语义化版本原则,使用^可以更方便地获取功能更新和bug修复。如果希望更谨慎地更新依赖,以避免可能引入的不兼容更改,使用~会更保险。

2024年6月29日 12:07 回复

See the NPM docs and semver docs:

  • ~version “Approximately equivalent to version”, will update you to all future patch versions, without incrementing the minor version. ~1.2.3 will use releases from 1.2.3 to <1.3.0.

  • ^version “Compatible with version”, will update you to all future minor/patch versions, without incrementing the major version. ^1.2.3 will use releases from 1.2.3 to <2.0.0.

See Comments below for exceptions, in particular for pre-one versions, such as ^0.2.3

2024年6月29日 12:07 回复

I would like to add the official npmjs documentation as well which describes all methods for version specificity including the ones referred to in the question

value

desc

~version

Approximately equivalent to version, i.e., only accept new patch versions
See npm semver - Tilde Ranges

^version

Compatible with version, i.e., accept new minor and patch versions
See npm semver - Caret Ranges

version

Must match version exactly

>version

Must be greater than version

>=version

Must be equal or greater than version

<version

Must be lesser than version

<=version

Must be equal or lesser than version

1.2.x

1.2.0, 1.2.1, etc., but not 1.3.0

*

Matches any version

latest

Obtains latest release

The above list is not exhaustive. Other version specifiers include GitHub urls and GitHub user repo's, local paths and packages with specific npm tags

Official Docs

2024年6月29日 12:07 回复

The package manager npm allows installing a newer package version than the one specified.
Using tilde (~) gives you bug-fix releases, while caret (^) in addition gives you backward-compatible new functionality.

The problem is that old versions usually don't receive bug fixes, so npm uses caret (^) as the default for --save.

SemVer table

Source: "SemVer explained - why there's a caret (^) in my package.json?".

Note that the rules apply to versions above 1.0.0. Not every project follows semantic versioning.
For versions 0.x.x the caret allows only patch updates, i.e., it behaves the same as the tilde.
See "Caret Ranges".

Here's a visual explanation of the concepts:

semver diagram

Source: "Semantic Versioning Cheatsheet".

2024年6月29日 12:07 回复

Semver

shell
<major>.<minor>.<patch>-beta.<beta> == 1.2.3-beta.2
  • Use npm semver calculator for testing. Although the explanations for ^ (include everything greater than a particular version in the same major range) and ~ (include everything greater than a particular version in the same minor range) aren't a 100% correct, the calculator seems to work fine.
  • Alternatively, use SemVer Check instead, which doesn't require you to pick a package and also offers explanations.

Allow or disallow changes

  • Pin version: 1.2.3.
  • Use ^ (like head). Allows updates at the second non-zero level from the left: ^0.2.3 means 0.2.3 <= v < 0.3.
  • Use ~ (like tail). Generally freeze right-most level or set zero if omitted:
  • ~1 means 1.0.0 <= v < 2.0.0
  • ~1.2 means 1.2.0 <= v < 1.3.0.
  • ~1.2.4 means 1.2.4 <= v < 1.3.0.
  • Ommit right-most level: 0.2 means 0.2 <= v < 1. Differs from ~ because:
    • Starting omitted level version is always 0
    • You can set starting major version without specifying sublevels.

All (hopefully) possibilities

Set starting major-level and allow updates upward

shell
* or "(empty string) any version 1 v >= 1

Freeze major-level

shell
~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

Freeze minor-level

shell
^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

Freeze patch-level

shell
~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)

Disallow updates

shell
1.2.3 1.2.3 ^0.0.3 (0.0.3) 0.0.3

Notice: Missing major, minor, patch or specifying beta without number, is the same as any for the missing level.

Notice: When you install a package which has 0 as major level, the update will only install new beta/pr level version! That's because npm sets ^ as default in package.json and when installed version is like 0.1.3, it freezes all major/minor/patch levels.

2024年6月29日 12:07 回复

As long as the first number ("major") is at least 1:

~ locks major and minor numbers. It is used when you're ready to accept only bug-fixes (increments in the third number), but don't want any other changes, not even minor upgrades that add features.

^ locks the major number only. It is used when you are willing to receive bug fixes (increments in the third number) and minor upgrades that add features but should not break existing code (increments in the second number). However you do not want changes that break existing code (increments in the first number).

In addition to that, ^ is not supported by old npm versions, and should be used with caution.

So, ^ is a good default, but it's not perfect. I suggest to carefully pick and configure the semver operator that is most useful to you.

(Revised to avoid saying "fixes" and "bug-fixes" with conflicting use of "fixes", which is confusing)

2024年6月29日 12:07 回复

你的答案