Semantic Versioning

Semantic Versioning and Version Ranges

Front-End Web Development introduces MAJOR.MINOR.PATCH. What matters in a Node project is the range you write down, because it decides which future releases install without you asking. npm 2,036 evaluates ranges with the semver package (github.com/npm/node-semver (https://github.com/npm/node-semver 5,467 ), ISC, currently 7.8.5), and you can run that resolver by hand:

Filtering versions through a range with the semver CLIShell
npx semver -r "^1.2.3" 1.2.3 1.9.0 2.0.0 1.2.2
Output
1.2.3
1.9.0

The caret is the default npm writes, and it means "anything that does not change the leftmost non-zero digit". That last clause is the trap: for ^0.2.0 the leftmost non-zero digit is the minor, so 0.3.0 is excluded. Pre-1.0 packages behave as if every minor bump were a major one.

Range syntax npm accepts, and the versions each one refuses
Range Matches Excludes
^1.2.3 1.2.3 to <2.0.0 2.0.0, 1.2.2
^0.2.0 0.2.0 to <0.3.0 0.3.0
~1.2.3 1.2.3 to <1.3.0 1.3.0
>=1.2 <2 || 3.x 1.9, 3.4 2.1
1.2.3 exactly 1.2.3 everything else

Prereleases are deliberately antisocial: ^1.2.3 matches neither 2.0.0-rc.1 nor 1.3.0-beta.1, because a range admits a prerelease only when it names that exact major.minor.patch tuple. Write ^1.2.3-0 to opt in.

When a transitive dependency pins something you need to move, an overrides object such as { "semver": "7.8.5", "some-plugin": { "glob": "$glob" } } rewrites the tree without forking. The $glob form means "whatever version the root already depends on", which keeps the override honest as you upgrade. pnpm 69,400 calls this pnpm.overrides; Yarn 11,798 calls it resolutions.