Wednesday, November 26, 2014

npm link with interdependent modules

Sometimes you need to develop on multiple interdependent node modules at the same time. When developing on a dependent module, in order to test your changes, you can do one of several things:

Publish your module and run npm update

Copy and paste code into your node_modules folder

Use npm link to use the in progress version of your module in your other applications

Out of any of the above options only 3 really scales and doesn't leave much potential for errors. Before going any further let's review what npm link does.

Let's say you have 2 modules:

dependent-module

master-module

master-module also has a dependency on dependent-module. Running npm link inside the dependent-module directory will create a symlink from that directory to the global node_modules/dependent-module directory. Then when running npm link dependent-module in the master-module directory will add dependent-module as a symlink inside the local node_modules directory. This allows you to make changes to dependent-module and instantly have them available inside master-module.

This works great until you have a module that is used in both of your modules that also has global state. A good example is mongoose, the excellent mongodb odm. Schemas and models are defined on the global mongoose object. If each of your modules has mongoose installed, they will have 2 different mongoose objects. So if your models are defined in one module, those models won't be available in your other module. Normally this behavior doesn't happen because npm is smart enough not to install module dependencies if they have already been installed, but when using npm link this won't be the case.

In order to avoid this problem, you will need to run npm link on any susceptible modules. So in our above example if both modules need mongoose, you will need to run npm link mongoose in each affected module directory.

Something to also keep in mind is that running npm update will destroy the symlinks, meaning you need to run npm link dependent-module and npm link mongoose after your run npm update.