Don't assume what's in your node_modules folder
Don't assume what's in your node_modules folder
NPM v3 has been out for a little while now, and with it has come a not insignificant change, the structure of the node_modules
folder has been largely flattened. If you're just using other modules within your project, then this change shouldn't really impact you. If you're publishing an npm module with dependency on other modules, however, then this change means that the dependencies of your module are likely to be in the root level node_modules
folder (relatively ../
) instead of a node_modules
folder within your module (relatively ./node_modules
).
The good news
So long as you're using require('some-module')
then npm will take care of looking in the right place for you, and everything will still work, hurray!
The issue
The complication I've seen comes when specifying a filepath to use in some other situation (like specifying a config file from another module). I've seen things similar to in a few places
var configPath = './node_modules/some-module/path/to/config.json'
and here's the tricky part: this works fine when you're developing your module. When working in your project folder, all modules will be in the node_modules
folder within it. The problem only rears its head after you're shipped it and it's installed inside the node_modules
folder itself, that's when ./node_modules/some-module
is actually at ../node_modules/some-module
- a sibling of your module, not a child.
require
to the rescue
Thankfully require
has some slightly lesser known applications that can help us get around this issue.
require
can get a file within a module, not just the module's base file:require('some-module/path-to/not-index.js')
will findsome-module
and then look forpath-to/not-index.js
within it.require
can resolve the location of a module instead of including it:require.resolve('some-module')
will give you the path to thesome-module
folder as a string- You can combine 1 and 2
Putting these together we can easily solve the problem from my previous example
var configPath = require.resolve('some-module/path/to/config.json');
and now never have to worry about where some-module
actually is, so long as npm knows.