Epoch semantic versioning | Anthony Fu
Semantic Versioning (SemVer) is both a much-needed industry standard and a complete albatross in terms of maintenance behaviour. Anthony agrees, and is proposing a
Originally discovered via this excellent video from Theo (T3), which breaks down the concept and adds some additional context. I'm intrigued that, since the video was released, Anthony has adopted Theo's suggestion (likely, it seems, made by quite a few people) to use a much larger "epoch" value.
On how Anthony currently "hacks" the SemVer methodology to behave more appropriately:
There’s a special rule in SemVer that states when the leading major version is
0
, every minor version bump is considered breaking. I am kind of abusing that rule to workaround the limitation of SemVer.
If you’ve been following my work in open source, you might have noticed that I have a tendency to stick with zero-major versioning, like
v0.x.x
. For instance, as of writing this post, the latest version of UnoCSS isv0.65.3
, Slidev isv0.50.0
, andunplugin-vue-components
isv0.28.0
.
On the core reason why we can't just stop using SemVer:
Package managers we use, like
npm
,pnpm
, andyarn
, all operate under the assumption that every package on npm adheres to SemVer.
On the human-perception issue of SemVer, and why major releases are often complete headaches:
However, humans perceive numbers on a logarithmic scale. We tend to see
v2.0
tov3.0
as a huge, groundbreaking change, whilev125.0
tov126.0
seems a lot more trivial, even though both indicate incompatible API changes in SemVer. This perception can make maintainers hesitant to bump the major version for minor breaking changes, leading to the accumulation of many breaking changes in a single major release, making upgrades harder for users.
On an ideal "epoch" based approach, that allows for both marketing hype and consistent breaking changes:
In an ideal world, I would wish SemVer to have 4 numbers:
EPOCH.MAJOR.MINOR.PATCH
. TheEPOCH
version is for those big announcements, whileMAJOR
is for technical incompatible API changes that might not be significant.
On how an "Epoch SemVer" can be translated/calculated:
The format is as follows:
{EPOCH * 1000 + MAJOR}.MINOR.PATCH