Detectar se chamado através de exigir ou diretamente pela linha de comando

Respostas:

471
if (require.main === module) {
    console.log('called directly');
} else {
    console.log('required as a module');
}

Consulte a documentação para isso aqui: https://nodejs.org/docs/latest/api/modules.html#modules_accessing_the_main_module

nicolaskruchten
fonte
3
Existe alguma maneira de contornar isso? Eu tenho um código (sobre o qual não tenho controle) que faz isso, mas preciso exigi-lo () e fazê-lo agir como se tivesse sido chamado diretamente. Basicamente, preciso enganar algo que usa esse teste para pensar que foi chamado diretamente.
21715 Kevin
2
@ Kevin Eu não sei como fazer isso require(), mas talvez você possa fazê-lo importando o arquivo e depois executando evalnele, ou executandorequire('child_process').exec('node the_file.js')
#
Ao usar módulos ES com Node.js, você pode usar o es-mainpacote para verificar se um módulo foi executado diretamente.
Tim Schaub
91

Existe outra maneira um pouco mais curta (não descrita nos documentos mencionados).

var runningAsScript = !module.parent;

Descrevi mais detalhes sobre como tudo isso funciona nos bastidores deste post do blog .

Thorsten Lorenz
fonte
+1, eu gosto mais disso, mas hesitarei antes de mudar as respostas aceitas. :)
Bryan Field
8
Como indiquei, a maneira oficial documentada é a @nicolaskruchten descrita. Esta é apenas uma alternativa, não há necessidade de mudar a resposta aceita. Ambos funcionam.
Thorsten Lorenz
10
Eu tive que usar isso em vez da maneira documentada - a maneira documentada funciona para, por exemplo. node script.jsmas não cat script.js | node. Dessa forma, funciona para ambos.
Tim Malone
9

Fiquei um pouco confuso com a terminologia usada nas explicações. Então eu tive que fazer alguns testes rápidos.

Eu descobri que estes produzem os mesmos resultados:

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

E para as outras pessoas confusas (e para responder diretamente à pergunta):

var isCLI = require.main === module;
var wasRequired = !isCLI;
prumo
fonte
5

Assim como em Python, sempre me pego tentando lembrar como escrever esse maldito trecho de código. Então, decidi criar um módulo simples para ele. Demorei um pouco para me desenvolver, pois o acesso às informações do módulo do chamador não é direto, mas foi divertido ver como isso poderia ser feito.

Portanto, a idéia é chamar um módulo e perguntar se o módulo chamador é o principal. Temos que descobrir o módulo da função de chamada. Minha primeira abordagem foi uma variação da resposta aceita:

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

Mas isso não garante que funcione. module.parentaponta para o módulo que nos carregou na memória, não aquele que está nos chamando. Se foi o módulo chamador que carregou esse módulo auxiliar na memória, tudo bem. Mas se não fosse, não teríamos como. Então, precisamos tentar outra coisa. Minha solução foi gerar um rastreamento de pilha e obter o nome do módulo do chamador a partir daí:

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;
};

Agora podemos fazer:

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

Ou mais legível:

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

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

Impossível de esquecer :-)

Lucio Paiva
fonte
2
Muito legal. Adoro quando trechos de código comuns são abreviados para um único nome. Pequeno ajuste:return require.main /*this is undefined if we started node interactively*/ && require.main.filename === callerModuleName;
masterxilo
4

Tente isso se você estiver usando os módulos ES6:

if (process.mainModule.filename === __filename) {
  console.log('running as main module')
}
Kebot
fonte
2
porcaria, meu process.mainModuleéundefined
datdinhquoc 17/10
1
GHOSHHHH, eu preciso verificar isso no meu .mjs arquivo
datdinhquoc