web-dev-qa-db-fra.com

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

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

Il semble que je ne trouve aucune information à ce sujet, mais cela semble être une partie assez importante de Node.js car je le vois souvent dans le code source. 

Selon la documentation Node.js :

module 

Une référence au courant module. En particulier module.exports est identique à l'objet exporté. Voir src/node.js pour plus d'informations.

Mais cela n'aide pas vraiment.

Que fait exactement module.exports et que serait un exemple simple?

1311
mrwooster

module.exports est l'objet renvoyé à la suite d'un appel require.

La variable exports est initialement définie sur ce même objet (c’est-à-dire un "alias" abrégé). Ainsi, dans le code du module, vous écririez généralement quelque chose comme ceci:

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

exporter (ou "exposer") les fonctions étendues en interne myFunc1 et myFunc2.

Et dans le code d'appel que vous utiliseriez:

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

où la dernière ligne montre comment le résultat de require est (généralement) juste un objet simple dont les propriétés peuvent être consultées.

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


Il convient de noter que le nom ajouté à l'objet exports ne doit pas nécessairement être identique au nom de portée interne du module pour la valeur que vous ajoutez, de sorte que vous pourriez avoir:

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

suivi par:

var m = require('./mymodule');
m.shortName(); // invokes module.myVeryLongInternalName
1518
Alnitak

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

Vous pouvez utiliser à la fois exports et module.exports pour 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 l'exemple de code ExpressJS) est que vous définissez les propriétés de l'objet exports dans un fichier .js que vous importez ensuite à l'aide de require().

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 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 renvoyant un seul objet et vous pouvez ajouter des propriétés (chaînes, nombres, tableaux, fonctions, etc.) à l'objet renvoyé en les définissant sur exports.

Parfois, vous voudrez que l'objet renvoyé d'un appel require() soit une fonction que vous puissiez 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 exports et module.exports est mieux expliquée dans cette réponse ici .

212
Jed Watson

Notez que le mécanisme du module NodeJS est basé sur CommonJS modules pris en charge dans de nombreuses autres implémentations telles que 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 à un nœud, je vous encourage vivement à utiliser exports au lieu de module.exportsqui ne fait pas partie du standard CommonJS et n'est généralement pas pris en charge par d'autres implémentations.

Une autre fonctionnalité spécifique à NodeJS est lorsque vous affectez une référence à un nouvel objet à exports au lieu de lui ajouter simplement des propriétés et des méthodes, comme dans le dernier exemple fourni par Jed Watson dans ce fil. Personnellement, je découragerais cette pratique car cela brise le support de référence circulaire du mécanisme des modules CommonJS. Il n'est alors pas supporté par toutes les implémentations et Jed example devrait alors être écrit de cette façon (ou une 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 les modules CommonJS, mais sans le support de référence circulaire (voir: Modules Appcelerator et CommonJS (mise en cache et références circulaires) )

59
Alexandre Morgaut

Quelques éléments à prendre en compte si vous affectez une référence à un nouvel objet à exports et/ou modules.exports:

1. Toutes les propriétés/méthodes précédemment attachées à la exports ou module.exports d'origine sont bien sûr perdues car l'objet exporté 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. Si l'une des variables exports ou module.exports fait référence à une nouvelle valeur, elles 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 difficile. Si vous changez la référence en exports et module.exports, il est difficile de dire quelle API est exposée (cela ressemble à module.exports gagne)

// 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() {}; 
32
Alexandre Morgaut

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

enter image description here

J'ai une vidéo sur module_export disponible ici

28
anish

Lorsque vous divisez le code de programme en plusieurs fichiers, module.exports est utilisé pour publier des variables et des fonctions pour l'utilisateur d'un module. L’appel require() de votre fichier source est remplacé par le module.exports correspondant chargé à partir du module.

Rappelez-vous lorsque vous écrivez 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 dans un module, tout ne doit pas être exporté.
  • L'objet module.exports est également disponible au format exports. Mais lorsque vous retournez une fonction unique, utilisez toujours module.exports.

module exports diagram

Selon: "Modules Part 2 - Rédaction de modules" .

17
pspi

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

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

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

vous devez faire plus attention: ne exportez pas override.

pourquoi ?

comme les exportations ne font que contenir 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 voulez seulement 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'expose qu'une fonction et la propriété de name est privée pour l'extérieur.

8
qianjiahao

Lorsque vous téléchargez et installez le fichier node.js, il existe des modules par défaut ou existants dans node.js, tels quehttp, sysetc. 

Comme ils sont déjà dans node.js, lorsque nous voulons utiliser ces modules, nous faisons essentiellement comme import modules, mais pourquoi? car ils sont déjà présents dans le fichier node.js. Importer, c'est comme les prendre à partir de node.js et les insérer dans votre programme. Et puis les utiliser.

Alors queExportsest exactement le contraire, vous créez le module que vous voulez, disons le module addition.js et en le mettant 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

Hein, c'est la raison, nous aimons

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

Attention au chemin

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

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

Lorsque vous exécutez ceci 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

Cela est dû au fait que le processus node.js ne peut pas ajouter.js car 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 !!

Une dernière chose, vous pouvez également exécuter le fichier addition.js en ne définissant pas NODE_PATH, à nouveau dans 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 en cours ./, cela devrait également fonctionner avec succès. 

5
JumpMan

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 inclut deux fonctions

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

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

Supposons que nous voulions augmenter l’utilité de la fonction dans un fichier différent, par exemple World.js. Dans ce cas, l’exportation d’un fichier entrait en image et pouvait être obtenue avec module.exports.

Vous pouvez simplement exporter la fonction à l'aide du code indiqué ci-dessous

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

Maintenant, il vous suffit de demander le nom du fichier dans World.js pour pouvoir utiliser ces fonctions.

var world= require("./hello.js");
2
Shantanu Madane

L'intention est:

La programmation modulaire est une technique de conception logicielle qui met l’accent sur séparer les fonctionnalités d'un programme en indépendantes, modules interchangeables, de sorte que chacun contienne tout le nécessaire pour n'exécuter qu'un aspect de la fonctionnalité désiré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 module.exports pour définir ce que nous exposons et composer 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;

programme.js

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

log('hello world!');

exécuter

$ node program.js

bonjour le monde!

Essayez maintenant de permuter ./stdoutLog.js pour ./fileLog.js.

1
Moriarty

Quel est le but d'un système de modules?

Il accomplit les choses suivantes:

  1. Garde nos fichiers de ballonnements à très grandes tailles. Avoir des fichiers avec par exemple Les 5000 lignes de code qu'il contient sont généralement difficiles à gérer au cours du développement.
  2. Impose la séparation des préoccupations. Le fait que notre code soit divisé en plusieurs fichiers nous permet d’avoir les 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é).

Les modules facilitent la recherche de certaines parties du code, ce qui rend notre code plus facile à gérer.

Comment ça marche?

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

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

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 qu'un require() est appelé sur le même module, il est extrait du cache.
  2. Les modules sont chargés de manière synchrone . Ce comportement est requis, s'il était asynchrone, nous ne pourrions pas accéder immédiatement à l'objet extrait de require().
0
Willem van der Veen