Detectar si se llama a través de require o directamente por línea de comando

Respuestas:

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

Consulte la documentación para esto aquí: https://nodejs.org/docs/latest/api/modules.html#modules_accessing_the_main_module

nicolaskruchten
fuente
3
¿Hay alguna forma de evitar esto? Tengo un código (sobre el que no tengo control) que hace esto, pero necesito requerirlo () y hacer que actúe como si se hubiera llamado directamente. Básicamente, necesito engañar a algo que usa esa prueba para pensar que se llamó directamente.
Kevin
2
@Kevin No sé cómo hacer esto require(), pero tal vez podrías hacerlo importando el archivo y luego ejecutándolo eval, o ejecutandorequire('child_process').exec('node the_file.js')
MalcolmOcean
Al usar módulos ES con Node.js, puede usar el es-mainpaquete para verificar si un módulo se ejecutó directamente.
Tim Schaub
91

Hay otra forma, un poco más corta (no descrita en los documentos mencionados).

var runningAsScript = !module.parent;

Esbocé más detalles sobre cómo funciona todo esto bajo el capó en esta publicación de blog .

Thorsten Lorenz
fuente
+1, me gusta más, pero dudaré antes de cambiar las respuestas aceptadas. :)
Bryan Field
8
Como indiqué, la forma oficial que se documenta es la que @nicolaskruchten describió. Esta es solo una alternativa, no es necesario cambiar la respuesta aceptada. Ambos trabajan.
Thorsten Lorenz
10
Tuve que usar esto en lugar de la forma documentada: la forma documentada funciona, por ejemplo. node script.jspero no cat script.js | node. De esta manera funciona para ambos.
Tim Malone
9

Estaba un poco confundido por la terminología utilizada en las explicaciones. Así que tuve que hacer un par de pruebas rápidas.

Descubrí que estos producen los mismos resultados:

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

Y para las otras personas confundidas (y para responder la pregunta directamente):

var isCLI = require.main === module;
var wasRequired = !isCLI;
Beto
fuente
5

Al igual que en Python, siempre me encuentro tratando de recordar cómo escribir este maldito fragmento de código. Entonces decidí crear un módulo simple para él. Me llevó un poco desarrollarlo ya que acceder a la información del módulo de la persona que llama no es sencillo, pero fue divertido ver cómo se podía hacer.

Entonces, la idea es llamar a un módulo y preguntarle si el módulo que llama es el principal. Tenemos que descubrir el módulo de la función de llamada. Mi primer enfoque fue una variación de la respuesta aceptada:

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

Pero eso no está garantizado para funcionar. module.parentseñala el módulo que nos cargó en la memoria, no el que nos llama. Si fue el módulo llamante el que cargó este módulo auxiliar en la memoria, está bien. Pero si no fuera así, estamos indefensos. Entonces necesitamos probar algo más. Mi solución fue generar un seguimiento de la pila y obtener el nombre del módulo de la persona que llama desde allí:

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

Ahora podemos hacer:

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

O más legible:

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

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

Imposible de olvidar :-)

Lucio Paiva
fuente
2
Muy genial. Me encanta cuando los fragmentos de código comunes se abrevian con un solo nombre. Pequeño ajuste:return require.main /*this is undefined if we started node interactively*/ && require.main.filename === callerModuleName;
masterxilo
4

Intente esto si está utilizando módulos ES6:

if (process.mainModule.filename === __filename) {
  console.log('running as main module')
}
Kebot
fuente
2
mierda, mi process.mainModuleesundefined
datdinhquoc
1
GHOSHHHH, necesito verificar esto en mi archivo
.mjs