Quel est le but de Node.js module.exports et comment l'utilisez-vous?

1432

Quel est le but de Node.js module.exports et comment l'utilisez-vous?

Je n'arrive pas à trouver d'informations à ce sujet, mais cela semble être une partie assez importante de Node.js comme je le vois souvent dans le code source.

Selon la documentation Node.js :

module

Une référence au courant module. Il module.exports est en particulier identique à l'objet exports. Voir src/node.jspour plus d'informations.

Mais cela n'aide pas vraiment.

Que fait exactement module.exportset quel serait un exemple simple?

mrwooster
la source

Réponses:

1590

module.exportsest l'objet qui est réellement retourné à la suite d'un requireappel.

La exportsvariable est initialement définie sur ce même objet (c'est-à-dire qu'il s'agit d'un "alias" abrégé), donc dans le code du module, vous écrivez généralement quelque chose comme ceci:

let myFunc1 = function() { ... };
let myFunc2 = function() { ... };
exports.myFunc1 = myFunc1;
exports.myFunc2 = myFunc2;

pour exporter (ou "exposer") les fonctions de portée interne myFunc1et myFunc2.

Et dans le code d'appel, vous utiliseriez:

const m = require('./mymodule');
m.myFunc1();

où la dernière ligne montre comment le résultat requireest (généralement) juste un objet simple dont les propriétés sont accessibles.

NB: si vous écrasez exportsalors il ne fera plus référence module.exports. Donc, si vous souhaitez affecter un nouvel objet (ou une référence de fonction) à, exportsvous devez également affecter ce nouvel objet àmodule.exports


Il convient de noter que le nom ajouté à l' exportsobjet ne doit pas nécessairement être le même que le nom de portée interne du module pour la valeur que vous ajoutez, vous pouvez donc avoir:

let myVeryLongInternalName = function() { ... };
exports.shortName = myVeryLongInternalName;
// add other objects, functions, as required

suivi par:

const m = require('./mymodule');
m.shortName(); // invokes module.myVeryLongInternalName
Alnitak
la source
119
Bonne réponse - il me semble que «exposer» aurait été un meilleur choix de terminologie que «exporter»
UpTheCreek
2
@ApopheniaOverload - vous pouvez faire "exports.func1, exports.func2, etc" pour avoir plusieurs méthodes exposées à partir d'un seul fichier.
hellatan
73
Le module require doit être var m = require ('./ mymodule'); , avec le point et la barre oblique. De cette façon, Node.js sait que nous utilisons un module local.
Gui Premonsa
7
Assurez-vous d'utiliser: la syntaxe require ('./ module_name') car, il pourrait y avoir d'autres modules node.js avec un certain nom et au lieu de choisir votre propre module, il reprendra celui qui est installé avec node.js
Sazid
3
@UpTheCreek il existe une longue tradition de référence aux symboles publics exposés par un module comme étant «exportés», qui remonte à de nombreux systèmes de programmation et décennies. Ce n'était pas un nouveau terme inventé par les développeurs de Node.
Mark Reed du
218

Cela a déjà été répondu, mais je voulais ajouter quelques éclaircissements ...

Vous pouvez utiliser les deux exportset module.exportspour importer du code dans votre application comme ceci:

var mycode = require('./path/to/mycode');

Le cas d'utilisation de base que vous verrez (par exemple dans le code d'exemple ExpressJS) est que vous définissez les propriétés de l' exportsobjet dans un fichier .js que vous importez ensuite à l'aiderequire()

Donc, dans un exemple de comptage simple, vous pourriez avoir:

(counter.js):

var count = 1;

exports.increment = function() {
    count++;
};

exports.getCount = function() {
    return count;
};

... puis dans votre application (web.js, ou vraiment tout autre fichier .js):

var counting = require('./counter.js');

console.log(counting.getCount()); // 1
counting.increment();
console.log(counting.getCount()); // 2

En termes simples, vous pouvez considérer les fichiers requis comme des fonctions qui renvoient un seul objet et vous pouvez ajouter des propriétés (chaînes, nombres, tableaux, fonctions, quoi que ce soit) à l'objet renvoyé en les activant exports.

Parfois, vous souhaiterez que l'objet renvoyé par un require()appel soit une fonction que vous pouvez appeler, plutôt qu'un simple objet avec des propriétés. Dans ce cas, vous devez également définir module.exports, comme ceci:

(sayhello.js):

module.exports = exports = function() {
    console.log("Hello World!");
};

(app.js):

var sayHello = require('./sayhello.js');
sayHello(); // "Hello World!"

La différence entre les exportations et module.exports est mieux expliquée dans cette réponse ici .

Jed Watson
la source
comment puis-je appeler nécessite un module d'un autre dossier qui n'a pas le dossier racine comme le mien?
Igal
@ user301639 vous pouvez utiliser des chemins relatifs pour parcourir la hiérarchie du système de fichiers. requirecommence par rapport au dossier node app.jsdans lequel vous exécutez . Je vous recommande de poster une nouvelle question avec du code explicite + des exemples de structure de dossier pour obtenir une réponse plus claire.
Jed Watson
1
J'ai dû modifier votre exemple module.exports pour le faire fonctionner. fichier: var sayHello = require('./ex6_module.js'); console.log(sayHello());et module:module.exports = exports = function() { return "Hello World!"; }
Jason Lydon
1
J'ai trouvé l'exemple d'incrémentation vraiment bon et je l'ai utilisé pour me rafraîchir l'esprit chaque fois que je suis surchargé par ce que je fais avec les exportations.
munkee
module.exports = exports = function(){...}le 2e exportsest juste une variable non? En d'autres termes, cela peut êtremodule.exports = abc = function()
Jeb50
60

Notez que le mécanisme du module NodeJS est basé sur des modules CommonJS qui sont pris en charge dans de nombreuses autres implémentations comme RequireJS , mais aussi SproutCore , CouchDB , Wakanda , OrientDB , ArangoDB , RingoJS , TeaJS , SilkJS , curl.js ou même Adobe Photoshop (via PSLib ). Vous pouvez trouver la liste complète des implémentations connues ici .

À moins que votre module n'utilise des fonctionnalités ou des modules spécifiques aux nœuds, je vous encourage fortement à les utiliser à la exportsplace de ceux module.exports qui ne font pas partie de la norme CommonJS et qui ne sont généralement pas pris en charge par d'autres implémentations.

Une autre caractéristique spécifique de NodeJS consiste à affecter une référence à un nouvel objet au exportslieu de simplement lui ajouter des propriétés et des méthodes comme dans le dernier exemple fourni par Jed Watson dans ce fil. Je découragerais personnellement cette pratique car cela rompt le support de référence circulaire du mécanisme des modules CommonJS. Il n'est alors pas pris en charge par toutes les implémentations et l'exemple Jed devrait alors être écrit de cette façon (ou similaire) pour fournir un module plus universel:

(sayhello.js):

exports.run = function() {
    console.log("Hello World!");
}

(app.js):

var sayHello = require('./sayhello');
sayHello.run(); // "Hello World!"

Ou en utilisant les fonctionnalités ES6

(sayhello.js):

Object.assign(exports, {
    // Put all your public API here
    sayhello() {
        console.log("Hello World!");
    }
});

(app.js):

const { sayHello } = require('./sayhello');
sayHello(); // "Hello World!"

PS: Il semble qu'Appcelerator implémente également des modules CommonJS, mais sans le support de référence circulaire (voir: Modules Appcelerator et CommonJS (mise en cache et références circulaires) )

Alexandre Morgaut
la source
35

Vous devez faire attention à quelques éléments si vous attribuez une référence à un nouvel objet exportset / ou modules.exports:

1. Toutes les propriétés / méthodes précédemment attachées à l'original exportsou module.exportssont bien sûr perdues car l'objet exporté en référencera désormais un autre nouveau

Celui-ci est évident, mais si vous ajoutez une méthode exportée au début d'un module existant, assurez-vous que l'objet exporté natif ne fait pas référence à un autre objet à la fin

exports.method1 = function () {}; // exposed to the original exported object
exports.method2 = function () {}; // exposed to the original exported object

module.exports.method3 = function () {}; // exposed with method1 & method2

var otherAPI = {
    // some properties and/or methods
}

exports = otherAPI; // replace the original API (works also with module.exports)

2. Dans le cas où l'une exportsou module.exportsréférencer une nouvelle valeur, ils ne font plus référence au même objet

exports = function AConstructor() {}; // override the original exported object
exports.method2 = function () {}; // exposed to the new exported object

// method added to the original exports object which not exposed any more
module.exports.method3 = function () {}; 

3. Conséquence délicate. Si vous changez la référence aux deux exportset module.exports, difficile de dire quelle API est exposée (cela ressemble à des module.exportsvictoires)

// override the original exported object
module.exports = function AConstructor() {};

// try to override the original exported object
// but module.exports will be exposed instead
exports = function AnotherConstructor() {}; 
Alexandre Morgaut
la source
29

la propriété module.exports ou l'objet exports permet à un module de sélectionner ce qui doit être partagé avec l'application

entrez la description de l'image ici

J'ai une vidéo sur module_export disponible ici

anish
la source
18

Lors de la division de votre code de programme sur plusieurs fichiers, module.exportsest utilisé pour publier des variables et des fonctions pour le consommateur d'un module. L' require()appel dans votre fichier source est remplacé par un correspondant module.exportschargé depuis le module.

N'oubliez pas lors de l'écriture des modules

  • Les charges de module sont mises en cache, seul l'appel initial évalue JavaScript.
  • Il est possible d'utiliser des variables et des fonctions locales à l'intérieur d'un module, tout n'a pas besoin d'être exporté.
  • L' module.exportsobjet est également disponible en exportsraccourci. Mais lorsque vous retournez une seule fonction, utilisez toujours module.exports.

module exporte le diagramme

Selon: "Modules Part 2 - Writing modules" .

pspi
la source
9

le lien de référence est comme ceci:

exports = module.exports = function(){
    //....
}

les propriétés de exportsou module.exports, telles que les fonctions ou les variables, seront exposées à l'extérieur

il faut faire plus attention: ne pas overrideexporter.

Pourquoi ?

car exporte uniquement la référence de module.exports, vous pouvez ajouter les propriétés aux exportations, mais si vous remplacez les exportations, le lien de référence sera rompu.

bon exemple :

exports.name = 'william';

exports.getName = function(){
   console.log(this.name);
}

mauvais exemple:

exports = 'william';

exports = function(){
     //...
}

Si vous souhaitez simplement exposer une seule fonction ou variable, comme ceci:

// test.js
var name = 'william';

module.exports = function(){
    console.log(name);
}   

// index.js
var test = require('./test');
test();

ce module n'a exposé qu'une seule fonction et la propriété du nom est privée pour l'extérieur.

qianjiahao
la source
6

Il y a des modules par défaut ou existants dans node.js lorsque vous téléchargez et installez node.js comme http, sys etc.

Comme ils sont déjà dans node.js, lorsque nous voulons utiliser ces modules, nous aimons essentiellement les modules d'importation , mais pourquoi? car ils sont déjà présents dans le node.js. L'importation revient à les retirer de node.js et à les placer dans votre programme. Et puis en les utilisant.

Alors que Exports est exactement le contraire, vous créez le module que vous voulez, disons le module addition.js et mettez ce module dans le node.js, vous le faites en l'exportant.

Avant d'écrire quoi que ce soit ici, rappelez-vous, module.exports.additionTwo est identique à exports.additionTwo

C'est la raison pour laquelle nous aimons

exports.additionTwo = function(x)
{return x+2;};

Soyez prudent avec le chemin

Disons que vous avez créé un module addition.js,

exports.additionTwo = function(x){
return x + 2;
};

Lorsque vous exécutez cela sur votre invite de commande NODE.JS:

node
var run = require('addition.js');

Ce sera une erreur de dire

Erreur: impossible de trouver le module addition.js

C'est parce que le processus node.js ne peut pas ajouter.js puisque nous n'avons pas mentionné le chemin. Donc, nous pouvons définir le chemin en utilisant NODE_PATH

set NODE_PATH = path/to/your/additon.js

Maintenant, cela devrait fonctionner sans erreur !!

Encore une chose, vous pouvez également exécuter le fichier addition.js en ne définissant pas le NODE_PATH, de retour à votre invite de commande nodejs:

node
var run = require('./addition.js');

Puisque nous fournissons le chemin ici en disant qu'il se trouve dans le répertoire courant, ./cela devrait également fonctionner correctement.

JumpMan
la source
1
est-ce l'exportation ou les exportations?
rudrasiva86
Merci pour l'aide :)
JumpMan
3

Un module encapsule le code associé dans une seule unité de code. Lors de la création d'un module, cela peut être interprété comme le déplacement de toutes les fonctions associées dans un fichier.

Supposons qu'il existe un fichier Hello.js qui comprend deux fonctions

sayHelloInEnglish = function() {
  return "Hello";
};
sayHelloInSpanish = function() {
  return "Hola";
};

Nous écrivons une fonction uniquement lorsque l'utilité du code est plus d'un appel.

Supposons que nous voulons augmenter l'utilité de la fonction dans un fichier différent, disons World.js, dans ce cas, l'exportation d'un fichier entre en image, ce qui peut être obtenu par module.exports.

Vous pouvez simplement exporter à la fois la fonction par le code donné ci-dessous

var anyVariable={
 sayHelloInEnglish = function() {
      return "Hello";
    };
  sayHelloInSpanish = function() {
      return "Hola";
    }; 
}
module.export=anyVariable;

Il vous suffit maintenant d'exiger le nom du fichier dans World.js pour utiliser ces fonctions

var world= require("./hello.js");
Shantanu Madane
la source
Merci Si cela vous a aidé, veuillez accepter ma réponse :)
Shantanu Madane
1
Un peu tard pour le copain du parti :)
Ben Taliadoros
@BenTaliadoros je pense aussi qu'il est en retard et je pense aussi que son objet anyVariable a beaucoup d'erreurs. la ligne au-dessus de la méthode sayHelloInSpanish ne doit pas se terminer par un point-virgule (;) et la fonction sayHelloInSpanish = est incorrecte. Tout va mal avec cet objet. je vais modifier sa réponse
divine
1
la modification est désactivée. Quoi d'autre alphadogg a-t-il modifié dans cette réponse ??
divine
Juste formatage. À moins que ce ne soit quelque chose d'es6 fou que je n'ai pas rencontré, et je suis certain que ce n'est pas le cas, alors ce n'est pas du tout JS valide
Ben Taliadoros
2

L'intention est:

La programmation modulaire est une technique de conception logicielle qui met l'accent sur la séparation de la fonctionnalité d'un programme en modules indépendants et interchangeables, de telle sorte que chacun contient tout le nécessaire pour exécuter un seul aspect de la fonctionnalité souhaitée.

Wikipédia

J'imagine qu'il devient difficile d'écrire un gros programme sans code modulaire / réutilisable. Dans nodejs, nous pouvons créer des programmes modulaires en utilisant la module.exportsdéfinition de ce que nous exposons et composons notre programme avec require.

Essayez cet exemple:

fileLog.js

function log(string) { require('fs').appendFileSync('log.txt',string); }

module.exports = log;

stdoutLog.js

function log(string) { console.log(string); }

module.exports = log;

program.js

const log = require('./stdoutLog.js')

log('hello world!');

exécuter

$ node program.js

Bonjour le monde!

Essayez maintenant de remplacer ./stdoutLog.js par ./fileLog.js .

Moriarty
la source
1

À quoi sert un système de modules?

Il accomplit les choses suivantes:

  1. Empêche nos fichiers de gonfler à de très grandes tailles. Il est généralement très difficile de gérer des fichiers contenant par exemple 5000 lignes de code pendant le développement.
  2. Applique la séparation des préoccupations. La division de notre code en plusieurs fichiers nous permet d'avoir des noms de fichiers appropriés pour chaque fichier. De cette façon, nous pouvons facilement identifier ce que fait chaque module et où le trouver (en supposant que nous ayons créé une structure de répertoire logique qui reste sous votre responsabilité).

Avoir des modules facilite la recherche de certaines parties de code, ce qui rend notre code plus facile à maintenir.

Comment ça marche?

NodejS utilise le système de modules CommomJS qui fonctionne de la manière suivante:

  1. Si un fichier veut exporter quelque chose, il doit le déclarer en utilisant la module.exportsyntaxe
  2. Si un fichier veut importer quelque chose, il doit le déclarer en utilisant la require('file')syntaxe

Exemple:

test1.js

const test2 = require('./test2');    // returns the module.exports object of a file

test2.Func1(); // logs func1
test2.Func2(); // logs func2

test2.js

module.exports.Func1 = () => {console.log('func1')};

exports.Func2 = () => {console.log('func2')};

Autres choses utiles à savoir:

  1. Les modules sont mis en cache . Lorsque vous chargez le même module dans 2 fichiers différents, le module ne doit être chargé qu'une seule fois. La deuxième fois que a require()est appelé sur le même module, il est extrait du cache.
  2. Les modules sont chargés en synchronisme . Ce comportement est requis, s'il était asynchrone, nous ne pourrions pas accéder require()immédiatement à l'objet récupéré .
Willem van der Veen
la source
-3
let test = function() {
    return "Hello world"
};
exports.test = test;
Gtm
la source
4
Il s'agit d'un exemple similaire à celui du premier extrait de la réponse acceptée ( return "Hello world"cela ne fait aucune différence), mais sans aucune explication. Veuillez vous assurer avant de répondre que votre réponse ajoutera quelque chose au sujet.
barbsan