Categories
node.js npm package.json semantic-versioning

What’s the difference between tilde(~) and caret(^) in package.json?

4620

After I upgraded to the latest stable node and npm, I tried npm install moment --save. It saves the entry in the package.json with the caret ^ prefix. Previously, it was a tilde ~ prefix.

  1. Why are these changes made in npm?
  2. What is the difference between tilde ~ and caret ^?
  3. What are the advantages over others?

5

5302

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. ^2.3.4 will use releases from 2.3.4 to <3.0.0.

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

20

  • 546

    Posting here to hopefully catch people that don’t quite think this through, but both ^ and ~ assumes you can trust minor and point releases from your dependencies. If you are publishing a library and want other people to trust you, DO NOT BLINDLY ACCEPT DOWNSTREAM DEPENDENCIES. A bad dot release from your dependency can cause a chain reaction upstream, and will have people knocking at YOUR door when things go pear shaped. This is another huge reason to use npm shrinkwrap on your production code.

    – tehfoo

    Feb 9, 2015 at 18:33

  • 36

    You can also just do away with all the nonsense of npm prepending your versions with a ^ or a ~. Set this if you want to have tight control over your versions: npm config set save-prefix=''

    Jul 8, 2015 at 6:11

  • 11

    @prasanthv is right: from 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. Allows changes that do not modify the left-most non-zero digit in the [major, minor, patch] tuple. In other words, this allows patch and minor updates for versions 1.0.0 and above, patch updates for versions 0.X >=0.1.0, and no updates for versions 0.0.X.

    – rofrol

    Oct 11, 2015 at 16:19

  • 32

    @jgillich in semver when you use 0.2.x, 2 isn’t a major version. That’s why docs.npmjs.com used the specific words: the left-most non-zero digit. Also what about this case: ^0.0.4 means 0.0.4

    – rofrol

    Oct 12, 2015 at 10:14


  • 15

    @FagnerBrack: The specific example you provided is correct, but generally your way of thinking is wrong. An example: let’s say you have package A in 3 versions: 0.0.1, 0.0.2 and 0.0.3. There is a bug in 0.0.1 so you want to have at least 0.0.2 in your package B. If you write 0.0.x you’ll get 0.0.3, which is OK. But if some other package C requires both B and A and additionally has constrain "A": "<0.0.2" you’ll get 0.0.1 without showing any conflict issue, which is not what you want. Using tilde ~0.0.2 should help you avoid this issue.

    – Maciej Sz

    Oct 22, 2015 at 14:22


1344

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

valuedesc
~versionApproximately equivalent to version, i.e., only accept new patch versions
See npm semver – Tilde Ranges
^versionCompatible with version, i.e., accept new minor and patch versions
See npm semver – Caret Ranges
versionMust match version exactly
>versionMust be greater than version
>=versionetc
<version
<=version
1.2.x1.2.0, 1.2.1, etc., but not 1.3.0
*Matches any version
latestObtains 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

7

  • 31

    It is also possible to specify an exact range of versions, like 1.2.0 || >=1.2.2 <1.3.0: Exactly 1.2.0, or everything from 1.2.2 to 1.3.0 (inclusive), but not 1.2.1, or 1.3.1 and above, and also not 1.1.x and below.

    – CodeManX

    Jun 8, 2016 at 20:30


  • 1

    A more specific link form the above -> docs.npmjs.com/files/package.json#dependencies

    – Toby

    Jul 11, 2018 at 12:38

  • 13

    "Approximately equivalent to version" and "Compatible with version" are such frustratingly non-specific ways to describe ~ and ^ behavior. Thank you @jgillich for providing an actual answer!

    Jul 17, 2019 at 15:21

  • Another resource : nodejs.dev/learn/semantic-versioning-using-npm

    – potame

    Jun 30, 2021 at 8:45

  • 1

    @Timo “deps that never depend on versions” probably don’t exist. You can have deps that don’t currently depend on versions, but future versions of the dependency are not guaranteed to be backwards compatible so unless you own the dependency as well as the application it’s a safe bet that eventually ‘latest’ won’t work. To me it seems the best use for a ‘latest’ specifier is during early development, proof-of-concepts, or for short term projects that will not be maintained long term.

    – Segfault

    Nov 17, 2021 at 14:11


838

npm allows installing newer version of a package than the one specified. Using tilde (~) gives you bug fix releases and caret (^) gives you backwards-compatible new functionality as well.

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

semver table

According to: “Semver explained – why there’s a caret (^) in my package.json?”.

Note that the rules apply to versions above 1.0.0 and 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”.

9

  • 2

    What about ^0.2.5? from 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. Allows changes that do not modify the left-most non-zero digit in the [major, minor, patch] tuple. In other words, this allows patch and minor updates for versions 1.0.0 and above, patch updates for versions 0.X >=0.1.0, and no updates for versions 0.0.X.

    – rofrol

    Oct 11, 2015 at 16:18

  • 18

    @rofrol any version before 1.0.0 is considered unstable and these rules don’t apply

    – pspi

    Nov 4, 2015 at 9:35

  • 3

    So your explanation isn’t complete

    – rofrol

    Nov 4, 2015 at 10:22

  • 7

    @rofrol yeah, omitting for readability is good sometimes, chances of having anything below 1.0.0 for a dependency in package json are pretty low. see also 20/80 principle, is a great rule for focusing on what matters

    – pspi

    Nov 4, 2015 at 16:42


  • 8

    @pspi Having versions below 1.0.0 is “unlikely”? Out of 60 we’ve got ~15, and most of them aren’t obscure.

    Aug 8, 2016 at 21:08