DEV Community

Gerald Hamilton Wicks
Gerald Hamilton Wicks

Posted on

Understanding npm Versioning: A Guide to Semantic Versioning and Version Operators

Have you ever opened your package.json and wondered what all those numbers and symbols mean? Something like this might look familiar:

"react": "^17.0.2"
Enter fullscreen mode Exit fullscreen mode

At first glance, it might seem like just a version number but there’s more happening here than meets the eye.

Those three numbers (17.0.2) follow a rule called Semantic Versioning, which tells you whether an update includes a small bug fix, a new feature, or a breaking change.

And what about the symbols like ^ or ~ in front of the version number? They’re just as important they control how npm decides which versions to install when you run npm install.

In this article, we’ll explore:

  • What each part of a version number means (major.minor.patch)
  • When to bump each version correctly
  • How to use ^, ~, and exact versions to manage dependency updates safely

By the end, you’ll know exactly what each number and symbol means and how to keep your project dependencies both stable and up to date.


What Is Semantic Versioning?

npm follows a system called Semantic Versioning (SemVer), where version numbers are divided into three parts separated by dots:

major.minor.patch
Enter fullscreen mode Exit fullscreen mode

Using the react example ("react": "^17.0.2"):

  • Major version: 17
  • Minor version: 0
  • Patch version: 2

Each part has a specific purpose in describing how the package has changed.


Patch Version

The patch number increases when backward-compatible bug fixes are released.

When to bump the patch:

  • Fixing small bugs
  • Patching security issues
  • Making internal improvements that don’t change the API

Example:

Before:

import { sumNumbers } from 'my-package';
Enter fullscreen mode Exit fullscreen mode

After a patch update, the internal behavior of sumNumbers might be improved but the way you use it stays the same.


Minor Version

The minor number increases when new features are added in a backward-compatible way.

When to bump the minor:

  • Adding new functions or options
  • Improving performance
  • Enhancing features without breaking existing code

Example:

Before:

import { sumNumbers } from 'my-package';
Enter fullscreen mode Exit fullscreen mode

After a minor update:

import { sumNumbers, subtractNumbers } from 'my-package';
Enter fullscreen mode Exit fullscreen mode

You gain a new feature (subtractNumbers), while existing code remains functional.


Major Version

The major number increases when breaking changes are introduced.

⚠️ When to bump the major:

  • Removing or renaming functions
  • Changing APIs or arguments
  • Modifying behavior in a way that requires updates to your code

Example:

Before:

import { sumNumbers } from 'my-package';
Enter fullscreen mode Exit fullscreen mode

After a major update:

import { addNumbers } from 'my-package';
Enter fullscreen mode Exit fullscreen mode

Since the function name changed, users must modify their code signaling a breaking change.


Version Operators in npm

When declaring dependencies in package.json, symbols like ^, ~, or no symbol define how npm handles version updates.


Caret (^)

Allows updates that do not change the leftmost non-zero version number typically minor and patch updates.

Example:

^4.13.6
Enter fullscreen mode Exit fullscreen mode

✅ Can update to: 4.14.0, 4.99.9
❌ Cannot update to: 5.0.0

Use case: Great balance between stability and receiving improvements.


Tilde (~)

Allows updates to the patch version only, within the specified minor version.

Example:

~4.13.6
Enter fullscreen mode Exit fullscreen mode

✅ Can update to: 4.13.7, 4.13.9
❌ Cannot update to: 4.14.0

Use case: Ideal when you want to lock features but still get bug fixes.


Exact Version (no symbol)

Locks the dependency to one specific version.

Example:

4.13.6
Enter fullscreen mode Exit fullscreen mode

✅ Always installs exactly version 4.13.6
❌ Will not update automatically

Use case: Maximum stability perfect for production-critical systems.


Summary

Symbol Allows Updates To Typical Use Case
^ Minor and patch versions (same major) Accepts new features and fixes safely
~ Patch versions only (same minor) Prioritizes stability with small updates
Exact No updates Ensures total consistency

In short:
Semantic versioning helps you understand what changed, while version operators control how updates happen. Together, they form the foundation of predictable and maintainable dependency management in npm.

Top comments (0)