Semantic versioning or SemVer for short is a software release standard that is designed to potentially eliminate confusion and helps to develop incremental software.
In this article, we will discuss some of the concepts related to SemVer which are crucial to understanding how it works. We will also analyze sample config files using the semVer style.
By the end of this article, you will have a better grasp of semantic versioning and especially, how it helps in building maintainable software.
A software's semantic version is usually denoted by a 3-part digit separated by a period.
For example:
1.4.22
Here, the first part gives us information about a major release of the software. The second part tells us about a minor release, and the third is about a patch release.
In other words, we have a "formula" like so:
Major.Minor.Patch
A release is regarded as a patch if it contains just some little bug fixes and maybe additional code.
It becomes a minor release if it contains a tangible amount of bug fixes and extra features.
And then, it's regarded as a major release when it contains changes that significantly alter the way it worked previously. These are called breaking changes.
Here are some use cases that provide more context to the importance of SemVer.
1. Publishing a package: If you wanted to write a package for the npm ecosystem, you will need a way of communicating with users(or dependents) of the package about the release(s).
2. Working with a third-party API: On the flip side, if we were depending on a package or external API, SemVer could help us foresee potential compatibility problems or identify bottlenecks.
3. Updating a codebase: Working with old codebases is inevitable. Whether it's a side project you are returning to or a new job. Semantic versioning can potentially help with damage control in this scenario.
The semantic versioning principle can also be instrumental in writing scalable software. For this context, two terms come in handy:
Backward compatibility in the NPM ecosystem is the ability of a software package or library to work seamlessly with code written using older versions of the same package.
This means that you may update the package without needing to tweak your existing code. The carat sign ^
is used to indicate that our app is backward compatible.
Forward compatibility, on the other hand, means that our codebase is kept open to new updates of the package without breaking the app.
The tilde sign ~
is used to denote this and it is usually a range of versions specified. Let's now break this down further using a sample package.json
file.
...
"dependencies": {
"sequelize": "^6.3.5",
"eslint": "~7.32.0",
"prettier": "^2.4.1"
},
...
Here, we notice that sequelize
uses the Caret ^
symbol for backward compatibility, which means our code is compatible with versions 6.3.6, 6.3.7,
6.3.8
up to 6.9.0
but not including 7.0.0
The next package eslint
uses the tilde sign ~
for forward compatibility, which means our code is compatible with versions 7.32.1,
7.32.4,
7.32.9
up to but not including any changes to the minor version number, that is 7.33.0
Our next package is prettier
. Prettier
is configured to be backward compatible. This means prettier
can only accept automatic updates from versions like 2.4.3,
2.5.1,
2.9.0
but not the major version number, that is 3.0.0
The alpha
, beta
and release
candidate
(rc)
tags are used to communicate software releases that are still in the test phases.
For example, the version history for babel/core
below shows version 8 in its pre-release or test mode.
8.0.0-alpha.1
8.0.0-alpha.0
With this in place, we are able to communicate with our users the current status of the tool. Babel package users can then choose whether to opt in for the test phase or stick with the regular package.
"The simplest thing to do is to start your initial development release at
0.1.0
and then increment the minor version for each subsequent release". (Source semver.org)
When we finally get to a version that is ready and fit for public consumption as it were, the SemVer becomes 1.0.0
In conclusion, we have talked extensively about semantic versioning; what it's all about as well as the practicality of this approach in building maintainable software, and we have also seen some practical use cases in real-world software tools.
Also published here.