Try to remember the last time you installed Node.js. I’ll guess you got it from nodejs.org, right?
Like everyone else following this route, after carefully (or not) pondering which version to pick, you just download an installer and you’re done:
npm are ready to use.
That will work fine for the most part and you won’t have to worry much until one day say you clone some legacy code and after running
npm install this happens:
$ npm i npm WARN ancient lockfile npm WARN ancient lockfile The package-lock.json file was created with an old version of npm, npm WARN ancient lockfile so supplemental metadata must be fetched from the registry. npm WARN ancient lockfile npm WARN ancient lockfile This is a one-time fix-up, please be patient... npm WARN ancient lockfile
Now you start wondering if there’s something wrong with your version. Did you clone the right repo or are you in an old branch? Should you really be using another version then and which version, anyway? Where is that documented? Should you go around asking people what
npm version they are using?
Soon you realize that likely the developers that created the project might have never updated their node installations and probably never ran into those warnings or any other problems since they are manually synced to other relevant environments. Also, possibly no dependency has been added in a long time and other developers never needed to update
package-lock.json, or they have been unaware or ignoring those warnings as well. So what’s the best next step here? Do we all go back to the old version, everyone updates node, or even should we just ignore it? If this is an ancient lockfile, it means someone out there is still using the old version and getting no warnings — will they ever upgrade their node installation?
Why does it matter, after all? In theory, there is some lockfileVersion retrocompatibility with older versions of node, although limited, so you could push the updates to the lock file and any older version would be able to understand it. Best case, though, with a compatible older version you should get this:
$ npm i npm WARN read-shrinkwrap This version of npm is compatible with lockfileVersion@1, but package-lock.json was generated for lockfileVersion@2. I'll try to do my best with it!
Of course, we hope for something better than “I’ll try” when resolving dependencies. Surely, npm should do a good job most of the time and it’s probably not that prone to bugs and inconsistencies because of different versions, but that marginal chance for errors will let you down when you at least expect and that version may not be compatible with future updates.
At this point, it is clear that many node versions are being used across the team (and likely release environments as well) and the de facto supported version number fell behind a long time ago in the codebase. As much as it might not be a big problem (at least not yet), all of this could have been avoided had everybody used the same node version for the project. But how is that possible? That’s where a Node.js version manager shines.
A version manager is, simply put, a tool that allows the user to switch between different versions of software, in this case, Node.js. There are many different takes on this out there, the most famous one being nvm; my personal favorite is Fast Node Manager or fnm, built in Rust and features cross-platform support, easy installation, and awesome speed.
You can check the installation instructions for your environment, but no matter the flavor you are just a one-liner away from having it installed. After that, it’s just a matter of calling
fnm use <version> and the next time you run
npm it’s going to be using that version number already. You can check all installed and available versions with
fnm list and
A good feature of most if not all node version managers is the ability to read configuration files, usually named
.nvmrc. In that previous scenario, we could have a file in the root folder of the project pointing to the latest LTS Node.js release which ships with npm v6:
That can also be a specific fixed version, like
v14.19.3 or just require a minor version constraint (
v14.19) to automatically increment patches or even only the major version (
v14) to use the latest minor version available when we run
fnm use or an equivalent for any other node version manager.
With another easy step we can make
fnm automatically read
.nvmrc in directories so it switches to the correct Node.js version automatically for us whenever we
cd into that folder, with virtually zero overhead since it’s insanely fast. It even prompts us to install a new version, if the installation is missing locally:
With that, we’ll rarely need to call
fnm again because it takes care of switching versions for us behind the scenes. Basically, the same effort as before, when we just had one version we weren’t so sure about.
In summary, besides the obvious benefit of being able to use multiple node versions in your dev environment, with this version manager + version configuration file combo you get:
fnm install <version>to install a new version in seconds.
Of course, this is not a miracle solution and has some limitations/boundaries:
.nvmrcin build pipelines or release environments. Some people argue that they are mainly meant to sync dev environments and can otherwise make things unnecessarily complex and coupled. If you are doing things correctly, your release environments should hardly need or care about switching node versions and the gymnastics involved in parsing those files to determine the node version dynamically may not be worth it. In any case, It Depends™, so use your best judgment.
defaultversions. If you want/need to manage different yarn versions that’s a whole other story and you might want to take a look at asdf.
I hope this captures how easy it is to install and switch between node versions with fnm or another version manager, and more importantly, how it can guarantee everyone uses the same software version in a project. That said, a version manager might still not be for you if you work on a single project or if you and your teammates prefer to navigate through node versions in another way.
I believe what most teams often overlook or fail to realize is that while npm manages the dependencies within a node environment, node itself is a project dependency and it should be managed and documented as possible — think about it the next time you find yourself wondering if Node.js versions matter.