Detect if called through require or directly by command line

后端 未结 5 996
南方客
南方客 2020-11-30 16:26

How can I detect whether my Node.JS file was called using SH:node path-to-file or JS:require(\'path-to-file\')?

This is the Node.JS equival

相关标签:
5条回答
  • 2020-11-30 17:02

    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;
    
    0 讨论(0)
  • 2020-11-30 17:13

    Try this if you are using ES6 modules:

    if (process.mainModule.filename === __filename) {
      console.log('running as main module')
    }
    
    0 讨论(0)
  • 2020-11-30 17:13

    I always find myself trying to recall how to write this goddamn code snippet, so I decided to create a simple module for it. It took me a bit to make it work since accessing caller's module info is not straightforward, 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 is the caller module that loaded this helper module into memory, we're good. But if it isn't, it won't work. 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;
    };
    

    Save this as is-main-module.js and now you can do:

    const isMainModule = require("./is-main-module");
    
    if (isMainModule()) {
        console.info("called directly");
    } else {
        console.info("required as a module");
    }
    

    Which is easier to remember.

    0 讨论(0)
  • 2020-11-30 17:16
    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

    0 讨论(0)
  • 2020-11-30 17:26

    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.

    0 讨论(0)
提交回复
热议问题