Using nvm and npm to Manage Node.js

Node.js v0.4.0 has been available for a week. I’ve been experimenting with Node for a while, and I think its going to be a big part of my toolkit in the future. It’s currently under active development, and at this early stage managing version conflicts can be a challenge. With the latest stable release, I took the opportunity to set up a better development environment.

Key to setting this up was using nvm, which stands for Node Version Manager. This let’s you run multiple versions of Node, each in an isolated environment. I currently have v0.2.6 and v0.4.0, and can easily switch between them. This makes it easy to update to the latest release, while still being able to fall back to the previous release when using modules that are not yet compatible with v0.4.0.

It’s worth noting that nave (Virtual Environments for Node), is an alternative to nvm. In fact, nave was recommended by Aaron Blohowiak at the last SF JavaScript Meetup I attended.

In comparing the two, one thing stood out to me. From nave’s credits:

Nvm is also really nice, but has to be sourced rather than being run, and thus is a little bit wonky for some use cases. But it doesn’t involve subshells, which makes it better for many others.

I’m comfortable sourcing things in my shell, and the concept of subshells didn’t quite sit well with me on first impression. So, I went the nvm route. It’s worth paying attention to both however, as neither is yet the de-facto Node version manager.

OK, let’s get into the details of installing and using nvm. First, we will install nvm using the recommended instructions. Clone the nvm repository into a .nvm directory.

$ git clone git://github.com/creationix/nvm.git ~/.nvm

nvm itself is just a shell function, which needs to be sourced in order to be available. To have it sourced in every terminal you open, put the following line in .bash_profile:

. ~/.nvm/nvm.sh

Since I was previously using v0.2.6 as my primary version of Node, I wanted to ensure that I also had that version available under nvm. The install process is as simple as stating which version is wanted.

$ nvm install v0.2.6

In my initial attempt, I got the following error: -bash: wget: command not found. Wget isn’t available by default on Mac OS X, and for some reason I hadn’t previously installed it. It’s a standard utility, however, and easy to install. Download wget-1.9.1.tar.gz and execute the following:

$ tar xvzf wget-1.9.1.tar.gz
$ cd wget-1.9.1
$ ./configure
$ make
$ sudo make install

With that problem resolved, we can reattempt installation of v0.2.6.

$ nvm install v0.2.6
$ which node
/Users/jaredhanson/.nvm/v0.2.6/bin/node

As you can see, nvm installed v0.2.6 into the .nvm directory it manages. You can also see the structure it sets up to allow for simultaneous installation of multiple versions. This is what we want.

This is like a fresh installation of Node, so we also need to reinstall npm and any additional modules we are using. This is done in the usual manner.

$ curl http://npmjs.org/install.sh | sh
$ which npm
/Users/jaredhanson/.nvm/v0.2.6/bin/npm

$ npm install connect

When modules are installed under an nvm environment, they are installed only for the version in use. You can see them by listing the contents of the version’s lib directory.

$ ls ~/.nvm/v0.2.6/lib/node
connect       npm        qs       wafadmin
connect@0.5.9 npm@0.2.18 qs@0.0.5

Now that we have recreated the v0.2.6 environment, including necessary modules, it is time to install v0.4.0.

$ nvm install v0.4.0

Easy. We can list the versions of Node we have installed using nvm ls.

$ nvm ls
v0.2.6
v0.4.0 *

With nvm use, we can switch between versions.

$ nvm use v0.2.6
Now using node v0.2.6
$ nvm use v0.4.0
Now using node v0.4.0

With v0.4.0 freshly installed, you’re probably eager to execute your application and see what happens. This eagerness will bite you though, resulting in something that looks like the following.

$ node main.js
...
Error: Cannot find module 'connect'
...

Remember, each version of Node managed by nvm maintains its modules separately from other versions. Each time you install a new version, you’ll also have to repeat the process of installing the modules you need using the usual npm install command.

$ npm install connect

This may seem like unnecessary bookkeeping, but it is in fact a good thing. New versions of Node introduce API and ABI changes that can break compatibility with existing modules. With modules associated with specific versions of Node, development is easier because compatibility issues are easier to isolate.

Comments

rick
says:
April 16, 2011 at 7:03 PM

Great explanation.
Is there anyway to create a .rvmrc file or equivalent for this thing?

Jared Hanson
says:
April 17, 2011 at 3:53 PM

Not that I’m aware of, but that would be incredibly useful.

Post a comment