Volta vs. nvm for JavaScript tooling

I work on several JavaScript projects that use nvm (Node Version Manager) for managing Node.js versions. I’ve recently started using Volta to replace nvm and have been very impressed.

I’ll explain the differences between Volta and nvm, and why I’m excited about Volta. Volta’s benefits stem from these two enhancements:

  • Volta installs and uses project-defined tools automatically.
  • Volta has better handling of global scripts.

A note before we start

All of the following assumes we’re working on a project that has added support for Volta. That’s as simple as finding the preferred Node.js and npm or yarn versions and running volta pin:

# cat .nvmrc
# grep -A3 engines package.json
        "engines": {
                "node": ">=10.0.0",
                "npm": ">=6.9.0"
# volta pin node@lts npm@6
success: pinned node@14.15.5 in package.json
success: pinned npm@6.14.11 in package.json

This will add a volta property to package.json which is how Volta keeps track of versions.

Magically get the right tool

nvm exists to handle Node.js versions, what makes Volta better? nvm requires you to either always run commands when switching projects (nvm use) or add helpers to your shell. These are surmountable, but Volta just handles it.

nvm will handle Node.js nicely, but what npm or yarn? Are you struggling with package-lock.json version changes as folks move from npm v6 to v7?

Volta has you covered, we pinned the tool in our project so we’ll always use that version. Check it out:

# node --version
# npm --version
# cd ..
# npm --version
# node --version
# cd -
# node --version

Magically get the right version of the right tool

That’s cool. My project just upgraded Node.js, what’s that like?

Volta knows the right tool for the job

Did I mention Volta knows the right tool?

I do a lot of TypeScript development and use tsc (the TypeScript compiler command line interface) a bunch. It’s handy to have tsc available globally, but different versions support different language features.

I can install tsc for use anywhere with npm install --global typescript, but when I switch to my project I have to remember to use its tsc from node_modules/.bin/tsc

Not with Volta. It will magically use the bin from your project if it’s included or the global install otherwise:

# volta install typescript@beta
success: installed typescript@4.2.0-beta with executables: tsc, tsserver
# tsc --version
Version 4.2.0-dev
# cd gutenberg/
# tsc --version
Version 4.1.3

Nice, right?

What else?

nvm keeps your global npm installs associated with a particular version of Node.js. That’s good because they don’t break when you switch versions, but annoying because the available scripts are completely different when you change Node.js versions.

Yeah, Volta handles. that. Global scripts are associated with the Node.js version that installed them so they’re stable.


Me too. Head to over to the Volta docs to get started, or run their installer and get rolling:

curl https://get.volta.sh | bash
volta install node@lts

You should be able to try nvm and Volta without fully committing by commenting out the the relevant block in your shell’s rc (e.g. ~/.bashrc). Look for the blocks like export NVM_DIR= or export VOLTA_HOME= and comment out the one you’d like to disable.

By Jon Surrell

Dad, coder, linguist, expat in Spain. I wrangle code @Automattic.

Leave a comment

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s