What's the difference between tilde(~) and caret(^) in package.json?
Solution 1
See the NPM docs and semver docs:
~version
“Approximately equivalent to version”, will automatically update you to all future patch versions that are backwards-compatible, without incrementing the minor version.~1.2.3
will use releases from1.2.3
to <1.3.0
.^version
“Compatible with version”, will automatically update you to all future minor/patch versions that are backwards-compatible, without incrementing the major version.^1.2.3
will use releases from1.2.3
to <2.0.0
.
See Comments below for exceptions, in particular for pre-one versions, such as ^0.2.3
Solution 2
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
Solution 3
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
.
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:
Source: "Semantic Versioning Cheatsheet".
Solution 4
Semver
<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
means0.2.3 <= v < 0.3
. - Use
~
(like tail). Generally freeze right-most level or set zero if omitted: ~1
means1.0.0 <= v < 2.0.0
~1.2
means1.2.0 <= v < 1.3.0
.~1.2.4
means1.2.4 <= v < 1.3.0
.- Ommit right-most level:
0.2
means0.2 <= v < 1
. Differs from~
because:- Starting omitted level version is always
0
- You can set starting major version without specifying sublevels.
- Starting omitted level version is always
All (hopefully) possibilities
Set starting major-level and allow updates upward
* or "(empty string) any version
1 v >= 1
Freeze major-level
~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
^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
~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
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.
Solution 5
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)