Globally set node_modules location for project

497 Views Asked by At

If I write

var moment = require('moment');

in my project, Node wastes a lot of time looking in places that do not actually contain the file, as this dtruss output shows.

       PID/THRD  RELATIVE SYSCALL(args)                 = return
 7079/0x7cf313:   1244530 stat64("/Users/burke/code/api/api/models/node_modules/moment\0", 0x7FFF5FBFE5D8, 0x9)          = -1 Err#2
 7079/0x7cf313:   1244575 stat64("/Users/burke/code/api/api/models/node_modules/moment.js\0", 0x7FFF5FBFE578, 0x9)               = -1 Err#2
 7079/0x7cf313:   1244595 stat64("/Users/burke/code/api/api/models/node_modules/moment.json\0", 0x7FFF5FBFE578, 0x9)             = -1 Err#2
 7079/0x7cf313:   1244612 stat64("/Users/burke/code/api/api/models/node_modules/moment.node\0", 0x7FFF5FBFE578, 0x9)             = -1 Err#2
 7079/0x7cf313:   1244628 stat64("/Users/burke/code/api/api/models/node_modules/moment.coffee\0", 0x7FFF5FBFE578, 0x9)           = -1 Err#2
 7079/0x7cf313:   1244663 open("/Users/burke/code/api/api/models/node_modules/moment/package.json\0", 0x0, 0x1B6)                = -1 Err#2
 7079/0x7cf313:   1244694 stat64("/Users/burke/code/api/api/models/node_modules/moment/index.js\0", 0x7FFF5FBFE578, 0x1B6)               = -1 Err#2
 7079/0x7cf313:   1244713 stat64("/Users/burke/code/api/api/models/node_modules/moment/index.json\0", 0x7FFF5FBFE578, 0x1B6)             = -1 Err#2
 7079/0x7cf313:   1244729 stat64("/Users/burke/code/api/api/models/node_modules/moment/index.node\0", 0x7FFF5FBFE578, 0x1B6)             = -1 Err#2
 7079/0x7cf313:   1244745 stat64("/Users/burke/code/api/api/models/node_modules/moment/index.coffee\0", 0x7FFF5FBFE578, 0x1B6)           = -1 Err#2
 7079/0x7cf313:   1244767 stat64("/Users/burke/code/api/api/node_modules/moment\0", 0x7FFF5FBFE5D8, 0x1B6)               = -1 Err#2
 7079/0x7cf313:   1244788 stat64("/Users/burke/code/api/api/node_modules/moment.js\0", 0x7FFF5FBFE578, 0x1B6)            = -1 Err#2
 7079/0x7cf313:   1244805 stat64("/Users/burke/code/api/api/node_modules/moment.json\0", 0x7FFF5FBFE578, 0x1B6)          = -1 Err#2
 7079/0x7cf313:   1244821 stat64("/Users/burke/code/api/api/node_modules/moment.node\0", 0x7FFF5FBFE578, 0x1B6)          = -1 Err#2
 7079/0x7cf313:   1244837 stat64("/Users/burke/code/api/api/node_modules/moment.coffee\0", 0x7FFF5FBFE578, 0x1B6)                = -1 Err#2
 7079/0x7cf313:   1244862 open("/Users/burke/code/api/api/node_modules/moment/package.json\0", 0x0, 0x1B6)               = -1 Err#2
 7079/0x7cf313:   1244887 stat64("/Users/burke/code/api/api/node_modules/moment/index.js\0", 0x7FFF5FBFE578, 0x1B6)              = -1 Err#2
 7079/0x7cf313:   1244904 stat64("/Users/burke/code/api/api/node_modules/moment/index.json\0", 0x7FFF5FBFE578, 0x1B6)            = -1 Err#2
 7079/0x7cf313:   1244920 stat64("/Users/burke/code/api/api/node_modules/moment/index.node\0", 0x7FFF5FBFE578, 0x1B6)            = -1 Err#2
 7079/0x7cf313:   1244936 stat64("/Users/burke/code/api/api/node_modules/moment/index.coffee\0", 0x7FFF5FBFE578, 0x1B6)          = -1 Err#2
 7079/0x7cf313:   1244964 stat64("/Users/burke/code/api/node_modules/moment\0", 0x7FFF5FBFE5D8, 0x1B6)           = 0 0
 7079/0x7cf313:   1244990 stat64("/Users/burke/code/api/node_modules/moment.js\0", 0x7FFF5FBFE578, 0x1B6)                = -1 Err#2
 7079/0x7cf313:   1245015 stat64("/Users/burke/code/api/node_modules/moment.json\0", 0x7FFF5FBFE578, 0x1B6)              = -1 Err#2
 7079/0x7cf313:   1245038 stat64("/Users/burke/code/api/node_modules/moment.node\0", 0x7FFF5FBFE578, 0x1B6)              = -1 Err#2
 7079/0x7cf313:   1245488 madvise(0x1008AE000, 0x21000, 0x9)             = 0 0
 7079/0x7cf313:   1245503 stat64("/Users/burke/code/api/node_modules/moment.coffee\0", 0x7FFF5FBFE578, 0x9)              = -1 Err#2
 7079/0x7cf313:   1245612 open("/Users/burke/code/api/node_modules/moment/package.json\0", 0x0, 0x1B6)           = 11 0

Is there a way to make Node not waste so much time looking in places that don't contain a node_modules directory? Like, I could set some kind of CHECK_HERE_FIRST=$HOME/code/api/node_modules environment variable and if the require is not for a relative path, that would be the first place that Node checked.

I could change all of my require lines to load the relative import but this seems cumbersome for a large project.

3

There are 3 best solutions below

0
On

I don't think that there is a elegant way to do this without changing require, which should be avoided. If you're worried about performance issues, it may help you sleep at night knowing that this only occurs once due to module caching.

Perhaps you can require all the modules you need during startup of your app.

0
On

According to node's docs, there's no way to change this behavior

If the module identifier passed to require() is not a native module, and does not begin with '/', '../', or './', then node starts at the parent directory of the current module, and adds /node_modules, and attempts to load the module from that location.

If it is not found there, then it moves to the parent directory, and so on, until the root of the file system is reached.

You should note that loaded modules are cached so performance shouldn't be an issue. If you are using Express, this loading process is done only at startup.

0
On

This behavior (making too many stat) has been removed (see PR) from io.js v2.3.1, it will be available in the next major version of node.js.