Skip to main content

Versioning

Good versioning communicates intent to consumers. It tells them whether an update is safe to adopt or requires migration work.

Semantic Versioning (semver)โ€‹

npm uses Semantic Versioning: MAJOR.MINOR.PATCH

BumpWhenExample
MAJORBreaking changes1.2.3 โ†’ 2.0.0
MINORNew features, backward-compatible1.2.3 โ†’ 1.3.0
PATCHBug fixes, backward-compatible1.2.3 โ†’ 1.2.4

When to bump whatโ€‹

  • MAJOR: Removed or renamed exports, changed function signatures, dropped Node.js version support
  • MINOR: New exported functions, new optional parameters, new features
  • PATCH: Bug fixes, performance improvements, documentation updates in code

Pre-release Versionsโ€‹

Use pre-release identifiers for unstable versions:

1.0.0-alpha.1
1.0.0-beta.1
1.0.0-rc.1

Publish pre-releases under a dist-tag to avoid affecting latest:

npm publish --tag next

The npm version Commandโ€‹

Bump versions directly from the command line:

npm version patch   # 1.2.3 โ†’ 1.2.4
npm version minor # 1.2.3 โ†’ 1.3.0
npm version major # 1.2.3 โ†’ 2.0.0

npm version prerelease --preid=beta # 1.2.3 โ†’ 1.2.4-beta.0

This command:

  1. Updates version in package.json
  2. Creates a git commit
  3. Creates a git tag (v1.2.4)

Dist-tagsโ€‹

Dist-tags are labels that point to specific versions:

TagPurpose
latestDefault install version (what npm install gets)
nextUpcoming major/pre-release channel
canaryBleeding-edge builds from main branch
# Publish to a specific tag
npm publish --tag next

# Install from a tag
npm install my-package@next

# Move a tag to a different version
npm dist-tag add my-package@2.0.0-rc.1 next

Conventional Commitsโ€‹

Conventional Commits is a commit message format that enables automated versioning:

feat: add streaming support        โ†’ MINOR bump
fix: handle null input gracefully โ†’ PATCH bump
feat!: redesign plugin API โ†’ MAJOR bump

chore: update dev dependencies โ†’ no release
docs: fix typo in README โ†’ no release

The format is: type(optional scope): description

Common types: feat, fix, chore, docs, refactor, perf, test, ci

Automated Versioning Toolsโ€‹

ToolApproachBest for
ChangesetsDevelopers add changeset files per PRMonorepos, team workflows
semantic-releaseFully automated from commit messagesSingle packages, CI-driven
release-itInteractive prompts + automationFlexible, single packages

Changesetsโ€‹

Changesets uses a file-based approach where developers declare version intent:

npx changeset          # Create a changeset describing your change
npx changeset version # Consume changesets, bump versions
npx changeset publish # Publish to npm

semantic-releaseโ€‹

semantic-release fully automates versioning based on commit messages. No manual intervention needed โ€” CI handles everything.

release-itโ€‹

release-it provides an interactive CLI for releases with support for changelogs, git tags, and npm publishing.

Version Ranges for Consumersโ€‹

When depending on packages, version ranges determine which updates are accepted:

RangeMeaningExample
^1.2.3Compatible with 1.x.x (โ‰ฅ1.2.3, <2.0.0)Default for npm install
~1.2.3Patch-level changes (โ‰ฅ1.2.3, <1.3.0)More conservative
1.2.3Exact version onlyMost restrictive
tip

For application projects, consider pinning exact versions and using tools like Dependabot or Renovate to manage updates. For libraries, use ^ ranges to allow flexibility for consumers.