Pragmatic Semantic Versioning

A relevant ad will be displayed here soon. These ads help pay for my hosting.
Please consider disabling your ad blocker on Pony Foo. These ads help pay for my hosting.
You can support Pony Foo directly through Patreon or via PayPal.

These are short-form “thoughts”, in addition to the usual longer-form articles in the blog. The goal is to publish one of these every weekday. I’d love to know what you think. You may send your questions to thoughts@ponyfoo.com. I’ll try to answer them over email and I may publish them here, with your approval. I also write thoughts about the current state of front-end development, and opinions on other people’s articles. You can use the form to the right (near the bottom in mobile) to subscribe via email.

When it comes to semantic versioning, the definition usually depends on who you ask. Everyone has their opinion on what constitutes a patch, what makes a minor, and what warrants a major version bump. In this article, I share my views. Keep in mind this is my opinion and it’s mostly constrained to the sort of software I release: open-source modules that are usually best served with a web browser.

I made the clarification above because in other sorts of software, enterprise grade stuff, you might want to be more “strict” about releases. Think Node.js or io.js. For the majority of us, though, this is not the case.

The consensual definition of semver more or less lies in the following bullet points.

  • patch whenever you release bug fixes that don’t affect the public API in the slightest
  • minor whenever you make a change that can potentially affect the public API, regardless of it being a bug fix or a new feature
  • major whenever you make a change that breaks expectations in the public API, such as removing an API touchpoint, changing its inputs, or its outputs

I prefer to take a pragmatic approach to versioning, as the above is usually a hassle. Bug fixes rarely break consumer code in practice, but almost always fall in the minor category. Consider a bug fix that someone else was using as a crutch and expected it to be a “feature”. That’s a minor because it breaks an expectation, even though it was a measly bug fix, and even though it wasn’t documented, and even though (chances are) nobody actually relied on it.

My approach is to consider these bug fixes that may or may not affect functionality a patch, rather than a minor. This brings me to point number two in this thought.

Getting Rid of Hats

Hats (and tildes) in package.json must die. Die in a fire. Die an ugly death where you burn them so they don’t come back as undead white walkers to frostbite you into an ugly death. Becoming one of them, in turn, and devouring your loved ones.

I’m of course talking about ^ and ~, but also about similarly dangerous operators like >= and *. Why would you take something as precious as npm's immutability and throw it under the bus is beyond me – yet it’s the default configuration value for npm.

After all the hard work that was put into (and is being put into) npm to fix dependency hell, using the mutable dependency operators ask too much from the community. Not everyone is going to be as gentle as you might think. I have had many dependencies break on my face after doing something innocuous like rm -rf node_modules ; npm i, and this shouldn’t be something to worry about. Your ability to deploy safely shouldn’t be lingering just on tests that make sure your dependencies didn’t break overnight.

There is no good reason why dependencies should be able to break overnight. I’ll take my safe deployments over your “minor bug fixes with chances of wreaking havoc” forecasts any day!

Run the following command. This madness ends today!

npm set save-exact true

Have any questions or thoughts you’d like me to write about? Send an email to thoughts@ponyfoo.com. Remember to subscribe if you got this far!

Liked the article? Subscribe below to get an email when new articles come out! Also, follow @ponyfoo on Twitter and @ponyfoo on Facebook.
One-click unsubscribe, anytime. Learn more.