Say goodbye to fickle
~ semver ranges
Uses sanever, a fork of node-semver, to rewrite your package.json
"devDependencies" etc.) to remove pesky
~ range specifiers leaving you with explicit ranges that are obvious in their intent and will have stability into the future (i.e. not relying on the meaning
~ being unchanging, because it hasn't been).
See sanever for full details of the alternative interpretation of how ranges should work. The summary is:
<1ranges no longer have special meaning for
~if ever changed by node-semver / npm). See npm/node-semver#92 for context. As of v2.0.0, according to npm's version of semver, a
^0.1.2range expands to exactly one version,
1.2.3, therefore a
~1.2.3should not include the pre-release
See rant below for more information about these changes.
Use your normal workflow to
npm install foo --save (etc.) and your preferred
~ if you
npm config set save-prefix '~') will be pre-pended to the latest version of that package. Then run
npm-explicit-deps to fix the prefixed range to an explicit range using the adjusted rules outlined above. To upgrade a package to the latest version from npm, simply
npm install foo@latest --save and run
npm-explicit-deps again to re-fix.
Or just fix up the
<1 ranges, which is where a lot of the trouble is.
npm-explicit-deps [--zeroOnly|-0] [--yes|-y]
Without arguments, will parse your package.json and rewrite all your dependencies with explicit version ranges. You will be shown a diff and asked whether or not you want to save the changes.
-0) will only modify the ranges in the
<1region, since these are the pesky ones with silly rules that you'll probably want to be explicit about.
-y) will not show you a diff and will save changes without prompting.
node-semver and npm have absurd rules for
<1 ranges that don't apply elsewhere. The
<1 rules are informed by the semver spec for what a
0 major version means, which is equally absurd.
A major version of
0 should not be a special case. It should not indicate anything other than you have not introduced any breaking changes since you first released your package. The semver spec says this:
Major version zero (0.y.z) is for initial development. Anything may change at any time. The public API should not be considered stable.
0, if we are introducing "stability" rules into our versioning, why does this only apply to
--tag dev(or some other tag) so they are not on the
latesttag and therefore not automatically installed. Linux pioneered the idea of using even versions for stable and odd for unstable and Node.js itself currently uses this pattern. Some projects will include a stability index to communicate stability measures to users.
<1 as a special case is bogus and should be avoided. My preference is to start a packages at
1.0.0 to avoid this. You will soon be able to
npm config set init.version 1.0.0 to automate this.
I strongly advise
npm config set save-prefix '~' to completely avoid the use of the
^ range specifier.
~ranges where the minor version is all that matters and the major version is only useful for communicating some vague sense of "major upgrade" and nothing more. This is changing, but like all culture changes it will take a long time before a more strict interpretation of semver is being used by developers publishing to npm.
^range will automatically include newer versions of dependencies to your library long after you've released it in a tested state. You should be exercising greater control over what dependencies are coupled with your libraries and applications or you're asking for trouble. Some Node.js developers go so far as to pin exact dependency versions and upgrade them explicitly. My current preference is to use the
~range so that my libraries can take advantage of patch releases. I don't want to take the risk of including wildly changing versions of a dependency, even if the fact that the major version hasn't changed is supposed to mean that there are no breaking changes. I don't trust myself enough to do versioning properly and consistently over a long period of time so why would I trust anybody else?
For the record, I'm attempting to follow proper semver (minus the
<1 sillyness) these days. But I'm still not going to be using
^ or recommend that people feel safe doing that when depending on my libraries!
~ range specifiers are unstable and may change into the future; this is out of your control. It's much more difficult to change the meaning of an explicit version range.
npm-explicit-deps is Copyright (c) 2014 Rod Vagg @rvagg and contributors licensed under the MIT License. All rights not explicitly granted in the MIT License are reserved. See the included LICENSE.md file for more details.