Version ranges and dist-tags

npm · Essentials · 12 min

Ranges decide which code you actually run after the next install.

You know ^1.4.2 and ~1.4.2. npm accepts the full node-semver grammar:

  • X-ranges: 1.x or 1 (any 1.y.z), * (anything).
  • Comparators: >=1.2.0 <1.5.0; combine with spaces (AND) and || (OR): ^2.0.0 || ^3.0.0.
  • Hyphen ranges: 1.2.3 - 1.4 means >=1.2.3 <1.5.0.
  • Prereleases like 2.0.0-beta.3 sort before 2.0.0 and are only matched by ranges that mention a prerelease of the same major.minor.patch. ^1.0.0 never installs 2.0.0-beta.1.

Dist-tags are named pointers to versions. latest is what npm install pkg gives you; maintainers publish betas under tags like next or beta so they do not become latest. Install one with npm install react@next, inspect with npm view react dist-tags.

Pinning: npm install -E pkg (--save-exact) writes 1.4.2 instead of ^1.4.2; npm config set save-exact true makes it the default. Since the lockfile already pins your installed tree, exact ranges mainly matter for tools whose updates you want to adopt deliberately, and for applications that prefer explicit upgrade PRs from bots like Renovate or Dependabot.

Libraries should use ranges (usually ^) so consumers can deduplicate shared dependencies.

Example

npx semver -r "^1.4.2" 1.4.1 1.9.0 2.0.0      # 1.9.0
npx semver -r "1.2.3 - 1.4" 1.2.3 1.4.9 1.5.0    # 1.2.3, 1.4.9
npx semver -r "^2.0.0 || ^3.0.0" 2.5.0 3.1.0 4.0.0  # 2.5.0, 3.1.0
npx semver -r "^1.0.0" 2.0.0-beta.1              # (nothing: prerelease excluded)

npm view vite dist-tags          # { latest: '8.x.y', beta: '...', ... }
npm install vite@beta            # install whatever "beta" points to
npm install -E typescript@5.9.3  # writes "typescript": "5.9.3"
npm install 'lodash@>=4.17.21 <5'

Remember

  • Ranges: ^, ~, x-ranges, comparators, || and hyphen ranges
  • Prereleases match only ranges that opt into them
  • Dist-tags (latest, next, beta) are movable pointers
  • -E pins exactly; libraries should keep ranges

Watch out for

  • Expecting ^1.0.0 to pick up 2.0.0-rc.1; prereleases of other versions never match.

Check yourself

  1. Which version satisfies `1.2.3 - 1.4`?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: docs.npmjs.com/cli/v11/using-npm/package-spec