Node.JS: Detect if called through require or directly by command line

有些话、适合烂在心里 提交于 2019-11-28 02:38:10
nicolaskruchten
if (require.main === module) {
    console.log('called directly');
} else {
    console.log('required as a module');
}

See documentation for this here: https://nodejs.org/docs/latest/api/modules.html#modules_accessing_the_main_module

Thorsten Lorenz

There is another, slightly shorter way (not outlined in the mentioned docs).

var runningAsScript = !module.parent;

I outlined more details about how this all works under the hood in this blog post.

I was a little confused by the terminology used in the explanation(s). So I had to do a couple quick tests.

I found that these produce the same results:

var isCLI = !module.parent;
var isCLI = require.main === module;

And for the other confused people (and to answer the question directly):

var isCLI = require.main === module;
var wasRequired = !isCLI;

Try this if you are using ES6 modules:

if (process.mainModule.filename === __filename) {
  console.log('running as main module')
}

Just like in Python, I always find myself trying to remember how to write this goddamn code snippet. So I decided to create a simple module for it. It took me a bit to develop since accessing caller's module information isn't straighforward, but it was fun to see how it could be done.

So the idea is to call a module and ask it if the caller module is the main one. We have to figure out the module of the caller function. My first approach was a variation of the accepted answer:

module.exports = function () {
    return require.main === module.parent;
};

But that is not guaranteed to work. module.parent points to the module which loaded us into memory, not the one calling us. If it was the caller module which loaded this helper module into memory, that's fine. But if it wasn't, we're helpless. So we need to try something else. My solution was to generate a stack trace and get the caller's module name from there:

module.exports = function () {
    // generate a stack trace
    const stack = (new Error()).stack;
    // the third line refers to our caller
    const stackLine = stack.split("\n")[2];
    // extract the module name from that line
    const callerModuleName = /\((.*):\d+:\d+\)$/.exec(stackLine)[1];

    return require.main.filename === callerModuleName;
};

Now we can do:

if (require("./is-main-module")()) {  // notice the `()` at the end
    // do something
} else {
    // do something else
}

Or more readable:

const isMainModule = require("./is-main-module");

if (isMainModule()) {
    // do something
} else {
    // do something else
}

Impossible to forget :-)

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!