Glossary / Dependency ranges

Dependency ranges

A dependency range is a version constraint that tells a package manager which published versions are eligible to satisfy a dependency. It expresses an update policy in package.json; the lockfile then records a particular resolution. Understanding range syntax prevents accidental broad upgrades and misleading assumptions about exactly what will install.

Common SemVer range forms

1.2.3 is an exact version. ^1.2.3 generally accepts compatible changes below 2.0.0; ~1.2.3 accepts patch-level updates below 1.3.0. Wildcards such as 1.2.x, comparator sets such as >=1.2 <2, hyphen ranges, and || alternatives are also supported by npm's semver grammar. Caret behavior is narrower for versions below 1.0.0 because leading zero components are treated specially; verify exact boundaries rather than assuming “caret means next major.”

Ranges may also use tags (latest), aliases (npm:other-package@range), URLs, git references, or local paths, which are package specifications but not ordinary SemVer ranges. Prerelease versions are excluded from many ordinary ranges unless the comparator explicitly includes a prerelease on the same tuple.

Range versus resolution

The range is not a promise that every install selects the same package: without a lockfile, the newest eligible version may change over time. Lockfiles constrain a concrete install, while updating the lock can select newer versions within ranges. A permissive range can be acceptable for an application with a committed lock; a library's peer range usually communicates the set of host versions it claims to support.

Engineering guidance

Choose ranges based on compatibility policy and release cadence. Review lockfile updates and test the actual resolved graph. Use exact pins only when deliberate, and avoid broad * ranges for production compatibility contracts. Document exceptions for prereleases, forks, and git dependencies because they weaken registry/version reproducibility.

Interview questions

  1. Does ^1.2.3 mean exactly 1.2.3? No; it permits compatible versions below the next breaking major according to SemVer range rules.
  2. Range vs lockfile? Range defines acceptable versions; lockfile records a selected graph.
  3. Why is caret special for 0.x? Leading zero components tighten the allowed range; exact boundaries should be checked with semver rules.
  4. Are prereleases always included? No, ordinary ranges often exclude them unless they explicitly include a matching prerelease comparator.
  5. Why can a library peer range be broad? It states the host versions the package claims to support and helps dependency resolution.

References