DEV Community

Vasily Malykhin
Vasily Malykhin

Posted on • Updated on

SemVer - Magic version 0

SemVer

Semantic Versioning defines a package version format and a set of rules that should be used when the package updates.

Under this scheme, version numbers and the way they change convey meaning about the underlying code and what has been modified from one version to the next.

A brief intro to SemVer: you can specify a version of a package using three groups of numbers: major.minor.patch. When you create a new version of your package, you should:

  1. Increment major if you introduced a breaking change.
  2. Increment minor if you added functionality in a backward-compatible manner.
  3. Increment patch if you made a backward-compatible bugfix.

This is pretty much it, although in documents you can find more details.

Version ranges

When you work with package managers which rely on semver (e.g. NPM), you can declare specific versions of dependencies or version ranges, which would allow you to update dependencies easier.

For example, you can use the caret(^) symbol to tell the package manager that all compatible versions are allowed:

// package.json
"dependencies": {
  "react": "^16.0.0"
}
Enter fullscreen mode Exit fullscreen mode

The above means that all versions of react up to (but not including) 17.0.0 are allowed. So when a new version of react is out, you can run npm update and it will download an updated version of it, update your package.json and a lock file.

Magic zero

But there is an exception for packages with major version equal to zero, e.g. 0.1.2.

Major version zero (0.y.z) is for initial development. Anything MAY change at any time. The public API SHOULD NOT be considered stable.

Technically, it is legitimate to introduce breaking changes, updating the minor digit of the package version. So, versions 0.1.2 and 0.2.0 won't be compatible.

To prevent potential breaking changes, when you do a minor update of a dependency, NPM treats versions a bit different:

Allows changes that do not modify the left-most non-zero element in the [major, minor, patch] tuple. In other words, this allows patch and minor updates for versions 1.0.0 and above, patch updates for versions 0.X >=0.1.0, and no updates for versions 0.0.X.

So, if you have a dependency ^0.1.2, npm update won't update it to 0.2.0, because only patch updates are allowed.
I didn't know this subtlety before and when an automatic update didn't work, I thought that it was due to some bug in NPM CLI :) Even worse, I updated the dependencies manually... Even though we had a lot of tests, how on Earth didn't I break anything?!

Anyways, if you depend directly or transitively on various 0.x.y versions of the same package, you can't do much. But as a package author, if you introduce a backward-compatible update to 0.x.y version, you'd better update patch instead of minor. That way the update process would be more streamlined for the package consumers.

P.S.

Online semver calculator - https://semver.npmjs.com/
Discussion related to pre-releases and magic zero - https://github.com/semver/semver/issues/221

Top comments (0)