Working on related Node.js modules locally

27 Dec 2013

It's a common scenario: your app depends on module foobar, and you need to make changes to it. Maybe it's a third-party module, and you're working on a pull request - or maybe you simply split your app in several composable modules that need to evolve together. The ideal way to approach it would be:

However things aren't always that clear, and sometimes we want to experiment a lot before publishing versions... or even committing any code.

Oh look, node_modules!

So it's safe to assume your app declares that other module as a dependency:

{
  "name": "myapp",
  "dependencies:" {
    "foobar": "1.0.3"
  }
}

and your folder structure looks something like:

/projects/myapp
   |__ server.js
   |__ package.json
   |__ node_modules
      |__ foobar
         |__ index.js

One tempting way to experiment is to make changes directly in node_modules/foobar/index.js. Easy done! However this doesn't play well with a standard workflow, not to mention version control, looking at changes etc... Lucky us, npm comes with a much more powerful feature.

npm link

npm link allows you to "mount" modules into other modules, bypassing the standard installation process to read straight from your disk. It's usually a 3 step process:

/projects/foobar  $ npm link
/projects/myapp  $ npm link foobar

That's it! Calling require('foobar') from within your app will automatically load the version you have on disk. You can make any changes and see their effect straight away.

Was it that easy?

The power of npm link is that there's nothing magical about it. The first command creates a symbolic link within the npm install directory, that no one uses yet:

/usr/local/share/npm/lib/node_modules/foobar -> /projects/foobar

The second command replaces your current "installed" version to point to that new symlink:

/projects/myapp/node_modules/foobar -> /usr/local/share/npm/lib/node_modules/foobar

So we're effectively creating a chain of symbolic links, that is completely transparent to how Node.js requires modules!

Epilogue

Once you're done, don't forget to call npm unlink foobar from your app's directory. This will remove the second link, and allow you to manage dependencies normally again.

As far as I know, there's no harm in leaving the first link alone, it could always come in handy next time!

Comments