web-dev-qa-db-fra.com

Node.JS: Détecter si appelé via require ou directement par ligne de commande

Comment savoir si mon fichier Node.JS a été appelé avec SH: node path-to-file Ou JS: require('path-to-file')?

Voici l'équivalent de Node.JS à ma question précédente en Perl: Comment puis-je exécuter mon script Perl uniquement s'il n'a pas été chargé avec require?

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

Voir la documentation à ce sujet ici: https://nodejs.org/docs/latest/api/modules.html#modules_accessing_the_main_module

410
nicolaskruchten

Il existe un autre moyen légèrement plus court (non décrit dans les documents mentionnés).

var runningAsScript = !module.parent;

J'ai présenté plus de détails sur la façon dont tout cela fonctionne sous le capot de cet article de blog .

80
Thorsten Lorenz

J'étais un peu dérouté par la terminologie utilisée dans les explications. J'ai donc dû faire quelques tests rapides.

J'ai trouvé que ceux-ci produisent les mêmes résultats:

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

Et pour les autres personnes confuses (et pour répondre directement à la question):

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

Essayez ceci si vous utilisez des modules ES6:

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

Comme en Python, je me retrouve toujours à essayer de me rappeler comment écrire ce foutu code. J'ai donc décidé de créer un module simple pour cela. Il m'a fallu un peu de développement, car accéder aux informations du module de l'appelant n'est pas simple, mais il était amusant de voir comment cela pourrait être fait.

L’idée est donc d’appeler un module et de lui demander si le module appelant est le module principal. Nous devons trouver le module de la fonction appelant. Ma première approche était une variante de la réponse acceptée:

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

Mais cela n'est pas garanti pour fonctionner. module.parent pointe sur le module qui chargé nous en mémoire, pas celui qui nous appelle. Si c'est le module appelant qui a chargé ce module auxiliaire en mémoire, c'est bien. Mais si ce n'était pas le cas, nous sommes impuissants. Nous devons donc essayer autre chose. Ma solution était de générer une trace de pile et d'obtenir le nom du module de l'appelant à partir de là:

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

Maintenant nous pouvons faire:

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

Ou plus lisible:

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

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

Inoubliable :-)

2
Lucio Paiva