Terminology
This is an oversimplification, but a semantic version consists of 3 parts: the major version, minor version, and patch version. For example, 1.2.3
has a major version of 1
, a minor version of 2
, and a patch version of 3
.
Example*
For the examples below, assume that the current package is app
and it depends
on dep1
. The published versions of dep1
are:
{
"dist-tags": { "latest": "1.2.2" },
"versions": [
"1.2.2",
"1.2.1",
"1.0.1",
"1.0.0",
"0.4.1",
"0.4.0",
"0.2.3",
"0.2.0",
"0.0.3",
"0.0.2",
"0.0.1"
]
}
Tilde (~) Dependencies
I'll start with tilde because it's the most consistent. It will give you the latest patch version without changing the major or minor version.
SemVer Range |
Your node_module Version After npm update --save |
~1.2.1 |
1.2.2 |
~1.0.1 |
1.0.1 |
~1.0.0 |
1.0.1 |
~1.0.0 |
1.0.1 |
~0.4.1 |
0.4.1 |
~0.4.0 |
0.4.1 |
~0.2.3 |
0.2.3 |
~0.2.0 |
0.2.3 |
~0.0.3 |
0.0.3 |
~0.0.2 |
0.0.3 |
~0.0.1 |
0.0.3 |
Caret (^) Dependencies >= v1.0.0 (a useful oversimplification)
Most think caret dependencies work like this: It will give you the latest minor version and patch version without changing the major version.
SemVer Range |
Your node_module Version After npm update --save |
^1.2.1 |
1.2.2 |
^1.0.1 |
1.2.2 |
^1.0.0 |
1.2.2 |
^1.0.0 |
1.2.2 |
But that's not the whole picture, this is only true when the major version is > 0. The next section explains how caret dependencies work regardless of the major version.
Caret (^) Dependencies
Here's a more comprehensive explanation: Imagine the major version, minor version, and patch version are elements of an array (e.g., [major, minor, patch]
). The caret dependency iterates the array until it finds the first non-zero, it "freezes" that non-zero in place, then it updates the next element(s) to the latest. In other words, assuming x
, y
, and z
represent numbers greater than 0:
^x.y.z
will update y
and z
to the latest.
^0.y.z
will update z
to the latest.
^0.0.z
won't update anything, because there is no element after z
.
Let's see this in action:
SemVer Range |
Your node_module Version After npm update --save |
^1.2.1 |
1.2.2 |
^1.0.1 |
1.2.2 |
^1.0.0 |
1.2.2 |
^1.0.0 |
1.2.2 |
^0.4.1 |
0.4.1 |
^0.4.0 |
0.4.1 |
^0.2.3 |
0.2.3 |
^0.2.0 |
0.2.3 |
^0.0.3 |
0.0.3 |
^0.0.2 |
0.0.2 |
^0.0.1 |
0.0.1 |
*: This language was taken from https://docs.npmjs.com/cli/v10/commands/npm-update#example and modified.
npm config set save-prefix=''
. (Stick~
in the quotes if that's what you prefer.) I personally do this and shrinkwrap for things in production.npm shrinkwrap
and package-lock.json vs npm-shrinkwrap.json #toSaveYouAGoogle (or two) -- fncomp mentions above and tehfoo below. Also, mneumonic:~
stays about even,^
goes up a little higher.