"Error: Cannot find module 'less'" Node.js module loading preference/order/cache?

Lance Pollard picture Lance Pollard · Feb 17, 2012 · Viewed 21k times · Source

Here's the situation… So I've created a Node.js module that acts as an interface to some Node.js template engines, Shift.js. That is included inside another Node.js module, Design.io (it's specified Design.io's package.json dependencies block). Design.io watches files for changes.

Then you build an app and require('design.io'). You also install, say, Less and Stylus into your project.

This way, when you save a .less or .styl file, a chain of methods are called:

  1. require("design.io") gets notified of the filesystem event. Design.io then calls
  2. require('shift').render(string, extension, callback). Shift.js then calls
  3. require(moduleFor(extension)) # require("less"). The string is compiled.

In my app (current working directory) I have installed less and stylus:

npm install less stylus

The problem I'm having is, in step 3 which is called from within the Shift.js module, I get errors like this:

Error: Cannot find module 'less'
    at Function._resolveFilename (module.js:334:11)
    at Function._load (module.js:279:25)
    at Module.require (module.js:357:17)
    at require (module.js:368:17)
    at Less.engine (/Users/viatropos/Documents/git/plugins/design.io/node_modules/shift/lib/shift/less.js:6:14)
    at Less.render (/Users/viatropos/Documents/git/plugins/design.io/node_modules/shift/lib/shift/less.js:18:21)
    at /Users/viatropos/Documents/git/plugins/design.io/node_modules/shift/lib/shift.js:69:23
    at /Users/viatropos/Documents/git/plugins/design.io/node_modules/async/lib/async.js:118:13
    at Object.forEachSeries (/Users/viatropos/Documents/git/plugins/design.io/node_modules/async/lib/async.js:134:9)
    at Object.render (/Users/viatropos/Documents/git/plugins/design.io/node_modules/shift/lib/shift.js:78:31)

My question is, why is this happening? I thought that you could dynamically require libraries from a module as long as they were installed somewhere… What am I missing?

The goal would be that libraries like Shift.js wouldn't have to define every single dependency in package.json… For an "interface to the template engines" library, that would require too many dependencies that the app would probably never be using.

Thanks for the help, hope that was somewhat clear.

Answer

user1207456 picture user1207456 · Feb 17, 2012

When you npm install foo, the foo module gets installed in a directory named node_modules in the current working directory.

When you install this shift library, it only looks for modules to require within its own node_modules directory, or in one of the global directories require.resolve() searches.

And that's the simple solution to your problem:

npm install -g less

And then the library is globally visible to all Node.js code on your computer, rather than only being visible to code in the current working directory.

Alternatively, if you only want shift to see it, then do something like this:

npm install shift
cd node_modules/shift
npm install less