43 comments

[ 3.9 ms ] story [ 94.7 ms ] thread
The article seems to be missing crucial examples, making it very hard to read and follow. :/
can't you install a private npm module by npm link? That won't touch the npm servers [1].

Then your other project in the same file system can just require like a first class public npm module.

[1] https://www.npmjs.org/doc/cli/npm-link.html

The OP did not read npm doc obviously. npm link is the killer feature of npm.
I don't think npm link is meant to be used in production like that.
You probably shouldn't be using npm for production builds. npm is good for libraries, but applications should probably be tarballed.
That was point of the article: npm is not a valid option for various reasons, but it should be easier for applications to organize the source code in multiple directories which you then tarball.
Setting an environment variable to include a directory in which you have libraries that you need to use across your application is not a workaround. It's using a feature.
So? Asking earnestly, what exactly is your point? That the title offends you because it uses the phrase "work around"?

Adding a relative path to a *PATH variable is clever, elegant, useful, and uncommon. It resolves a problem not directly (by changing how 'require' works internally), but indirectly, aka "working around" it.

I've done this in the past on *nix systems, for Perl. I modified PERL5LIB from my .bashrc file, so that my project lib was looked for by default. This, rather than having to put 'use lib '../../../yikes/ugly' ahead of any inclusion of project modules.

Another approach, which I favor now, is to place modules directly into the default locations, such as /usr/lib/share/perl5 and etc.--usually there are a number of paths Perl looks at by default. It's then just a matter of saying 'use MyModule;' in code.

Is node.js similar, in having one or more include paths set by default, and could files be put there, to where you never have to refer to something by relative location again?

How this would work with browserify?
Article appears to be down.

I've never worked on a Node project with directories that nested more than 3 or 4 levels deep, so I don't see this as a "problem" (but maybe the article makes a case that it is).

The fix for this is to use a module. Simple. Not a problem.
For me, a relative path in a require statement signifies that the required code is a part of the application itself.

Consider:

    require('foo');
Versus:

    require('./foo');
If I find that a module is becoming popular, I may turn it into an npm module by moving it to it's own folder and adding a package.json, then using npm's bundledDependencies property to inform npm that it lives locally.

(edit: Note that I've shifted my perspective on the module when this happens. The shift is from "This code is in a separate module to keep my application organized" to "This code is in a separate module because it has some logical independence from the application.")

If the module needed even more independence, I'd move it to it's own git repo and create an internal mirror of the npm repo so that it can be discovered internally, and unbundle it from my app. (I could see this happening especially with larger teams, or teams that embrace the "module all the things" philosophy.)

And of course, there's always the possibility of moving the module out to the public npm repos and hosting it there.

I've never had require with relative paths of more than two or three "double dots". (Note to self: Look up what those things are called formally.)

The double dots refer to the parent directory; I'm not sure that there is other associated terminology or if there is an easier way to express what you wrote.
If find it's easier to distinguish modules from files by requiring modules like:

  require('foo');
and application files like:

  require('./foo.js'); //.js extension
Imagine if you're requiring that local module throughout your codebase. Now suppose that the module has become large enough to be come a directory. All those requires with the .js extension will break! If you leave it off, then no problem. Always avoid adding the .js.
While I don't personally do this - I try to follow node idiom of having each package be a relatively thin layer of functionality and having packages depend on each other, I believe that you don't need to use relative paths if you don't want to.

For example, if your package is called my-node-module and you have something in my-node-module/lib/app/dir/thingy/wotsit/jimminy.js, it can reference something in my-node-module/lib/server/alf.js by simply going

    require("my-node-module/lib/server/alf.js");
There's no need for the relative path at all. It's possible that this only works if your package is in an node_modules directory (which it will be if it's installed as a dependency), but I always symlink my development directory to node_modules anyway.
There are lots of workarounds. My preferred workaround isn't especially good, but it keeps me sane since I also hate having giant relative paths. https://gist.github.com/jdc0589/9115898

Usage is as follows:

    var pRequire("./projectRequire")(rootPathOfYourProject);
    var MyModule = pRequire("~/lib/foo/bar/myModule");
It doesn't really buy you anything over `require("nameOfYourPackage/path/to/module")`, but I like the consistent "~" prefix across projects using the same scheme.

Moving things to their own NPM package is a great solution when its something re-usable that logically makes sense to exist on it's own, but that isn't the case most of the time.

Python can help with this problem.
This is half of why I much prefer .NET's namespacing. The other half is not having to declare every single thing a file full of code exports for use.
Anyone with this problem is most likely working on a horrible monolith. You have far too much nesting and you're simply hiding the symptoms of a greater problem. Flat > nested. Simple > complex. Law of demeter also applies to reaching and in/out of folders. Break your app into more smaller modules rather than sweeping your mess under the rug.
+100 — NODE_PATH actually ends up being an anti-pattern because all of those internal modules are still not versionable. Instead, use a private NPM registry and just publish everything separately.
Put one of the following in your package.json "postinstall" hook:

    npm link lib
    link -s lib node_modules/lib
Then:

    require('lib/models/user')
No matter where you are.
That is a code smell. node and require works really great with small modules. npm link in development, tarball up and scp to your box for deployment.
I've been using the AngularJS dependency injection module for all my application code, [1] which means I am now only requiring libraries. I find it makes for much cleaner code and easier to test as well.

[1] https://github.com/FungusHumungus/pongular

A simple convention, as long as you know the process root:

var rootDir = process.cwd(); var config = require(rootDir + '/server/config');

And so forth.

(comment deleted)
If you use requirejs for node, defining paths in requirejs.config solves this problem too.
Your project is horribly architected if you need to do relative requires this deep.

Applications can be decoupled into interoperable components. Separate modules for configuration, controllers, routing, etc.

Separate concerns into modules.