Semantic Versioning (SemVer)
Semantic Versioning is a versioning system that gives meaning to version numbers. Understanding semver is essential for managing dependencies safely.
The Format
MAJOR.MINOR.PATCH
│ │ │
│ │ └── Bug fixes (backwards compatible)
│ └──────── New features (backwards compatible)
└────────────── Breaking changes
Example: 4.17.21
- MAJOR:
4 - MINOR:
17 - PATCH:
21
Version Increment Rules
| Change Type | Example | When |
|---|---|---|
| MAJOR (4.0.0 → 5.0.0) | Breaking changes | Incompatible API changes |
| MINOR (4.17.0 → 4.18.0) | New features | Backwards-compatible additions |
| PATCH (4.17.20 → 4.17.21) | Bug fixes | Backwards-compatible fixes |
Pre-release Versions
For unstable releases:
1.0.0-alpha.1 # Early testing
1.0.0-beta.1 # Feature complete, testing
1.0.0-rc.1 # Release candidate
Version Ranges in package.json
npm uses special characters to specify acceptable versions:
Caret (^) - Default
Allows MINOR and PATCH updates:
"lodash": "^4.17.21"
Matches: 4.17.21, 4.17.22, 4.18.0, 4.99.99
Does NOT match: 5.0.0
Tilde (~)
Allows only PATCH updates:
"lodash": "~4.17.21"
Matches: 4.17.21, 4.17.22, 4.17.99
Does NOT match: 4.18.0
Exact Version
No updates allowed:
"lodash": "4.17.21"
Matches: only 4.17.21
Comparison Operators
"lodash": ">4.0.0" // Greater than
"lodash": ">=4.0.0" // Greater or equal
"lodash": "<5.0.0" // Less than
"lodash": "<=5.0.0" // Less or equal
"lodash": ">=4.0.0 <5.0.0" // Range
Hyphen Range
"lodash": "4.0.0 - 4.99.99"
Equivalent to >=4.0.0 <=4.99.99
X-Range
"lodash": "4.x" // Any 4.x.x version
"lodash": "4.17.x" // Any 4.17.x version
"lodash": "*" // Any version
Or (||)
"lodash": "^3.0.0 || ^4.0.0"
Version Comparison Examples
What each allows:
| Specifier | Allows |
|---|---|
^1.2.3 | 1.2.3 to 1.x.x (not 2.0.0) |
~1.2.3 | 1.2.3 to 1.2.x (not 1.3.0) |
1.2.3 | Only 1.2.3 |
>=1.0.0 <2.0.0 | 1.0.0 to 1.x.x |
1.x | 1.0.0 to 1.x.x |
* | Any version |
Why Caret is the Default
The caret (^) is npm's default because:
- Allows bug fixes - You get patch updates automatically
- Allows new features - Minor updates are included
- Prevents breaking changes - Major versions are blocked
- Balance - Between stability and updates
Common Versioning Patterns
Conservative (Maximum Stability)
{
"dependencies": {
"express": "4.18.2"
}
}
Use exact versions for critical dependencies.
Standard (Recommended)
{
"dependencies": {
"express": "^4.18.2"
}
}
Allow minor and patch updates.
Liberal (Living Dangerously)
{
"dependencies": {
"express": "*"
}
}
Not recommended for production!
npm's Version Commands
# Check if updates are available
npm outdated
# Update packages within semver range
npm update
# View available versions
npm view lodash versions
# Install latest version
npm install lodash@latest
Understanding npm outdated
npm outdated
Output:
Package Current Wanted Latest Location
lodash 4.17.20 4.17.21 4.17.21 my-project
express 4.17.0 4.18.2 4.18.2 my-project
react 17.0.2 17.0.2 18.2.0 my-project
| Column | Meaning |
|---|---|
| Current | Installed version |
| Wanted | Max allowed by semver range |
| Latest | Latest on npm |
Practice: Semver Matching
Which versions match the specifier ^2.3.4?
| Version | Match? |
|---|---|
| 2.3.4 | Yes |
| 2.3.5 | Yes |
| 2.4.0 | Yes |
| 2.99.99 | Yes |
| 3.0.0 | No |
| 2.3.3 | No |
| 1.0.0 | No |
Best Practices
- Use caret (^) for most dependencies
- Use exact versions for critical packages
- Run npm outdated regularly
- Update carefully - read changelogs
- Lock versions with package-lock.json
Key Takeaways
- SemVer format: MAJOR.MINOR.PATCH
- Caret (^): Allows minor + patch updates
- Tilde (~): Allows only patch updates
- Exact: Pins to specific version
- npm outdated: Shows available updates
What's Next?
Let's explore npm scripts and how to automate common tasks in your project.

