Structuring Library Functionality in Node.js Projects

Recently I needed to start thinking about adding reusable “library” components to an Express.js node.js project, and I hit a bit of a brick wall. The library functionality was fairly specific to the application, and it just doesn’t make that much sense to break it out as seperately-packaged module right now. Seems like a fairly common use-case, right? Well, apparently not. You can load any filepath through the require() system, like so:

var module = require('./lib/myModule');
...

But where this can quickly become a nuisance is when you are nested down a deep folder hierarchy:

var module = require('../../../lib/myModule');
...

Having to track the folder hierarchy is a little bit of an inconvience, especially when compared to the convience of the NPM module system. Searching around for some solutions, I found issues with the approaches commonly suggested:

  • Modify the paths where require.js scans for modules - In previous versions of node, it looks like you could modify the paths require.js searched through, but this method has been deprecated and was not a “best practice” while available.
  • Load the path to your library directory into a global - I wanted to figure out a way around needing to declare some application-wide globals. doing something like this might also create some unit testing concerns.
  • Utilize npm-link - This seemed great at first blush, but the actual mechanics of how npm-link works are a little perculiar. Npm-link first symlinks a specified module in your project directory to the global npm module location. Then, it’s symlinks that global location to a module in your local project’s node_modules directory. This means naming collisions could occur if you tried to use this method with two projects on the same machine.
  • Just put your library modules in the node_modules directory! - Right now, this project’s node_modules directory only includes community packages, and they’re all installed through package.json. This provides nice separation in the code – node_modules is not our code, everything else is. The node_modules directory is actually ignored in source control to disuade developers from mucking around with our open-source libraries.

Npm-link got me thinking though, and a co-worker clued in on that too. We could create a “library” module, which acted mostly as a namespace for our project’s unique library-type functionality. Each of those unique pieces would be submodules of the “library” module. Then, we can create a symlink from the node_modules directory to the library directory, and commit that symlink into our source control. Now our code can look like this:

var module = require('lib/myModule');
...

Example folder structure

We get the benefits of keeping our code outside of the node_modules directory, but with the benefits of it living within the require() lookup path. It’s working out great so far, and I’m happy we ended up finding a very straightforward solution to our problem.

Hello, I'm Andrew Winder. I work at Message Systems as a Senior Software Engineer, and I blog here about AngularJS, Node.js, and other technical topics. All opinions are my own.