123 votes

Comment puis-je obtenir le chemin d'un module que j'ai chargé via require et qui *n'est pas* le mien (c'est-à-dire dans un node_module)

Je ai besoin d'un module qui a été installé via npm. Je veux accéder à un fichier .js subordonné à ce module (afin que je puisse sous-classer une méthode constructeur dedans). Je ne peux pas (enfin, je ne veux pas) modifier le code du module, donc je n'ai pas d'endroit pour extraire son __dirname.

Je suis conscient de la question suivante, mais elle concerne l'obtention du chemin d'un module sur lequel on a le contrôle du code (donc, __dirname est la solution) : En Node.js, comment puis-je connaître le chemin de ce module?

\~~~

Mieux encore serait d'obtenir les informations du module chargé

0 votes

Avez-vous pu charger le module sans erreur avec require('nomdumodule')?

0 votes

Pouvez-vous l'expliquer plus clairement ? Des exemples de code ?

155voto

Linus G Thiel Points 18378

Si j'ai bien compris votre question, vous devriez utiliser require.resolve():

Utilisez le mécanisme interne require() pour rechercher l'emplacement d'un module, mais au lieu de charger le module, renvoyez simplement le nom de fichier résolu.

Exemple: var pathToModule = require.resolve('module');

17 votes

Cette réponse ne fonctionne pas de manière fiable avec tous les modules de nœud. Voir ma réponse.

1 votes

Cette réponse ne fonctionne pas pour moi, voir la réponse de @Jason.

0 votes

ReferenceError: require n'est pas défini dans esm, comment le résoudre en esm ?

114voto

Jason Points 880

require.resolve() est une réponse partielle. La réponse acceptée peut fonctionner pour de nombreux modules node, mais ne fonctionnera pas pour tous.

require.resolve("nomDuModule") ne vous donne pas le répertoire où le module est installé; il vous donne l'emplacement du fichier défini dans l'attribut main dans le package.json du module.

Cela pourrait être nomDuModule/index.js ou cela pourrait être nomDuModule/lib/nomDuModule.js. Dans le dernier cas, path.dirname(require.resolve("nomDuModule")) renverra un répertoire que vous ne voulez peut-être pas ou ne vous attendez pas: _node_modules/nomDuModule/lib_

La bonne façon d'obtenir le chemin complet vers un module spécifique est de résoudre le nom du fichier:

let cheminReadme = require.resolve("nomDuModule/README.md");

Si vous voulez juste le répertoire pour le module (peut-être que vous allez faire beaucoup d'appels à path.join()), alors résolvez le package.json — qui doit toujours être à la racine du projet — et passez à path.dirname():

let cheminPackage = path.dirname(require.resolve("nomDuModule/package.json"));

2 votes

Très bonne réponse, en détectant le fichier package.json. Ne devriez-vous pas utiliser path.join('moduleName', 'package.json') pour être compatible avec Windows?

5 votes

@JoãoPimentelFerreira require.resolve est indépendant de la plate-forme, tout comme require, il n'est donc pas nécessaire d'utiliser path.join

2 votes

N'oubliez pas d'ajouter const path = require('path'); avant d'utiliser path.dirname.

3voto

Alexee Points 267

Pour information, require.resolve renvoie l'identifiant du module selon CommonJS. Dans node.js, il s'agit du nom de fichier. Dans webpack, il s'agit d'un numéro.

Dans la situation de webpack, voici ma solution pour trouver le chemin du module :

const pathToModule = require.resolve('module/to/require');
console.log('pathToModule est', pathToModule); // un numéro, par exemple 8
console.log('__webpack_modules__[pathToModule] est', __webpack_modules__[pathToModule]);

Ensuite, à partir de __webpack_modules__[pathToModule], j'ai obtenu des informations comme celles-ci :

(function(module, exports, __webpack_require__) {

    eval("module.exports = (__webpack_require__(6))(85);\n\n//////////////////\n// 
    WEBPACK FOOTER\n// délégué ./node_modules/echarts/lib/echarts.js à partir de dll-référence vendor_da75d351571a5de37e2e\n// id du module = 8\n// morceaux de module = 0\n\n//# sourceURL=webpack:///delegated_./node_modules/echarts/lib/echarts.js_from_dll-reference_vendor_da75d351571a5de37e2e?");

    /***/
})

Il s'est avéré que j'avais requis d'anciens scripts de la construction précédente du fichier dll (pour une compilation plus rapide), de sorte que mon fichier de module mis à jour ne fonctionnait pas comme je m'y attendais. Finalement, j'ai reconstruit mon fichier dll et résolu mon problème.

Réf : Utilisation de require.resolve pour obtenir le chemin du fichier résolu (node)

3voto

trusktr Points 4518

La réponse de Jason était la meilleure réponse, jusqu'à ce que Node.js ESM et le exports soit sorti.

Maintenant que Node prend en charge les packages avec un champ exports qui par défaut va empêcher les fichiers comme package.json d'être résolus à moins que l'auteur du package décide explicitement de les exposer, le tour de magie de la réponse de Jason échouera pour les packages qui n'exposent pas explicitement package.json.

Il y a un package appelé resolve-package-path qui fait l'affaire.

Voici comment l'utiliser :

const resolvePkg = require('resolve-package-path')

console.log(resolvePkg('@some/package'))

ce qui produira quelque chose comme

/chemin/vers/@some/package/package.json

peu importe ce que contient le champ exports du package.

0 votes

Je soupçonne que lorsque un auteur exporte consciemment une partie du contenu du module, vous êtes sur un terrain encore plus instable, car l'auteur a maintenant défini formellement son interface publique. Cela tendrait, je pense, à entraîner une refonte plus agressive des éléments qui ne sont pas explicitement exportés, n'est-ce pas?

1 votes

@Jason C'est vrai pour les fichiers source, mais les fichiers package.json ne vont pas disparaître. Je ne vois aucune raison pour lesquels ils devraient être masqués de l'importation.

1 votes

Si vous cherchez spécifiquement package.json au lieu des autres fichiers, alors oui, mais ce n'est qu'une variante de la question en cours. Je pense vraiment que nous devrions tous pousser pour que l'objet module contienne le contenu du fichier package.json afin de ne plus avoir à faire des choses stupides comme celle-ci.

1voto

Anatoliy Points 7775

J'espère avoir correctement compris vos besoins : obtenir le fichier de point d'entrée de certains modules. Disons que vous voulez obtenir le point d'entrée du module jugglingdb :

node
> require('module')._resolveFilename('jugglingdb')
'/usr/local/lib/node_modules/jugglingdb/index.js'

Comme vous pouvez le voir, ce n'est pas la manière "officielle" d'obtenir ce genre d'information sur un module, donc le comportement de cette fonction peut changer d'une version à l'autre. Je l'ai trouvé dans la source de node : https://github.com/joyent/node/blob/master/lib/module.js#L280

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X