You've started creating your own npm modules, giving code back to the open source community and getting it debugged and improved for free in the bargain. It's fun and easy. But it's also a hassle, publishing your module over and over just to use the latest version in your own project. In this article I'll explain how to use "npm link" to develop npm modules without pain in tandem with the projects that inspired them - and how to avoid doing it all with root privileges.
Creating npm modules: being famous and awesome isn't hard
Just about everybody in the Node community is developing and releasing npm modules for everyone else to use. Node was born well after the simplest business case for open source was well-understood: other people using your stuff "for free" are also debugging and improving it "for free." Whether to open source those tricky bits of readily reusable code isn't even a question in the Node community.
Creating an npm module is ridiculously easy. Create a free, public github repository, clone it to a folder on your computer, type "npm init," answer some questions and you're up and running. Type "npm install --save underscore" in your module's folder to add other npm modules that your module depends on (like, say, underscore) and they are automatically added to your package.json file. Every time you have a new release for the masses to appreciate, type "npm publish". Now everyone (including you) can bring that module into any project with "npm install" and use "require" to summon it into their code, just as they would with any other npm module. It ain't hard.
What is hard is figuring out a good workflow for developing both an npm module and a project that depends on it at the same time.
The obvious way is to maintain your npm module in one folder (let's say, src/appy) and your project in another (src/mysite). Every time you make a change to the appy module, you run "npm publish" and wait. Then, back in src/mysite, you run "npm update" and wait...
Seriously? That sounds pretty painful. Yeah, it is pretty painful for a module that's evolving rapidly in concert with an app that's driving your progress. Fortunately there's an easier way. Enter "npm link."
npm link: symbolic links to the rescue
Fortunately npm provides a tool to avoid this tedium. And it's easy to use. But there's a catch.
Here's how it's supposed to work:
1. cd to src/appy
2. Run "npm link". This creates a symbolic link from a global folder to the src/appy folder.
3. cd to src/mysite
4. Run "npm link appy". This links "node_modules/appy" in this particular project to the global folder, so that "require" calls looking for appy wind up loading it from your development folder, src/appy.
Mission accomplished... almost. If you installed Node in a typical way, using MacPorts or Ubuntu's apt-get, then npm's "global" folders are probably in a location shared system-wide, like /opt/local/npm or /usr/lib/npm. And this is not good, because it means those "npm link" commands are going to fail unless you run them as root.
Get away from sudo: npm without root
Running everything as root is both tedious and not a good idea. So let's fix our npm installation so that we don't run things as root anymore:
1. Fire up your editor and open the file ".npmrc" in your home directory (note the leading dot).
2. Add this line, substituting the location of your home directory for mine, of course:
prefix = /Users/boutell/npm
3. Create that folder:
Now npm will install and look for things in ~/npm/bin (the ~ stands for your home directory) rather than in a global folder that only root can write to. You have your own personal npm, and you can run "npm link" without root privileges.
Just remember that any command line tools you install with "npm install -g", such as "forever," are going to wind up in ~/npm/bin. So let's fix that by adding a line to ~/.profile (or ~/.bashrc if that's your preference):
Start a new terminal window and you'll find that commands installed in ~/npm/bin can now be found.
4. One more catch: you probably have a folder called ~/.npm. And if you've been running npm commands with sudo (stop doing that! Never do it again!), you'll get errors when you try to use "npm link" because it can't overwrite what's already there.
It's easy to clean this up, because there is nothing in ~/.npm that can't be recreated by running npm commands again. But just to be on the safe side, let's move it aside:
mv ~/.npm ~/.npm-old-and-busted
Now "npm link" should work for you exactly as advertised. You can make changes "live" in src/appy and they will be immediately visible when "require"d by src/mysite. You can still run "npm publish" when you have a new stable release that's worth publishing to the rest of the world.
That's all it takes! Now you have a recipe for painless npm development. Go publish that amazing module we're all waiting for.