The first time you open up a package.json file you're greeted by a lot of information about that project. That one file can include a lot of information about the project: the author's name and email, the project title, where the project is hosted, where to submit bugs, startup scripts, and more. The parts that I'm going to discuss in this post are found within the dependencies and devDependencies sections.
Frequently you will see module version numbers prefixed with a '~' or '^' and sometimes you'll even see just a '*'. What exactly do these characters correlate with respect to version numbers? When you run
npm install, the '~', '^', and '*' tell npm what versions of the dependencies to install for the project. So how do those characters relate to version numbers at all?
The numbers listed there certainly make sense, but what do the other characters mean? After all you know what version of software you wanted when you required the module, why would you want or need anything else? Well these characters help provide flexibility on what versions of dependencies are installed when the
npm install command is run. Let's take a look at what each one does and why that functionality is useful.
Semantic Versioning Breakout
Real quick before we dive into the what the characters do, let me first give a brief overview of the software versioning system that npm modules use. They follow the Semantic Versioning, or semver, specification. These map to a x.y.z numbering system, eg 1.2.3 would be major version 1, minor version 2, and patch version 3.
What exactly do major, minor, and patch mean with respect to software versions? The following information has been taken directly from the SemVer website:
- MAJOR version when you make incompatible API changes,
- MINOR version when you add functionality in a backwards-compatible manner, and
- PATCH version when you make backwards-compatible bug fixes.
For an expanded look at semantic versioning, I wrote a previous post about the subject that can be found here. Alright let's jump back into the the examination of the '~', '^', and '*' characters!
~, ^, and *? Oh I see what they do now...
Let's start by looking at the '~'. The '~' character fixes both the major and minor version numbers, while matching any patch number. e.g. if the version dependency was defined as ~2.3.1, npm would match all versions greater than or equal to 2.3.1 and less than 2.4.0 for that dependency.
Next up is the '^', which locks down the major version number, but leaves the minor and patch versions to be more flexible. When installing a dependency that is listed with the version of ^2.2.3, npm will match any version that is greater than or equal to 2.2.3 and also less than 3.0.0.
Finally there is the '*', which while available, isn't used as often. The primary reason for its less frequent use is the fact that it acts as a stand in for either the major, minor, or patch number and catches any version number for the place that it represents. For example a dependency with a version of '*' would equate to any version that was greater than or equal to 0.0.0, while 1.* would allow versions greater than or equal to 1.0.0 and less than 2.0.0.
Importance of Dependency Versions
Gaining a greater understanding how the versioning system works in the package.json file will hopefully help you to avoid dependency hell down the line. Take a little bit of time now to familiarize yourself with the system that the package.json file uses, so you can avoid headaches later. Also take some time to review the semver specification, so you can properly version your own software in the future!