web-dev-qa-db-fra.com

Quelle est l'utilité de exports / module.exports?

Aujourd'hui, j'ai adopté Browserify pour mon projet AngularJS, mais il y a quelque chose qui n'est pas très clair pour moi. Dans tous les exemples et articles de blog, j'ai vu des trucs comme ça:

/app.js:

require('./messages');
angular.module('sling', ['sling.messages']);

/messages/index.js:

exports = angular.module('sling.messages', [])
    .controller('MessagesListCtrl', require('./MessagesListCtrl'));

/messages/MessagesListCtrl.js:

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

Bien sûr, cela fonctionne, mais pourquoi faire cela? Je l'ai implémenté comme ça et cela fonctionne très bien aussi et semble plus normal pour un projet AngularJS:

/app.js:

require('./messages');
angular.module('sling', ['sling.messages']);

/messages/index.js:

angular.module('sling.messages', []);
require('./MessagesListCtrl');

/messages/MessagesListCtrl.js:

angular.module('sling.messages').controller('MessagesListCtrl', function() {
    // ...
});

En d'autres termes, je saute complètement les exports/module.exports, en utilisant uniquement require pour inclure essentiellement les fichiers avec les contrôleurs, les services, le filtre, etc.

Suis-je en train de faire ça? Je veux dire que tout fonctionne, mais vais-je avoir des ennuis plus tard?

15
Kevin Renskers

La raison principale (et honnêtement seulement) d'utiliser Browserify est si vous voulez avoir des modules CommonJS (c'est-à-dire des modules NodeJS) dans le navigateur. Un module CommonJS reste hors de la portée globale en ayant une portée "module" implicite. Vous choisissez les éléments à exposer à partir de la portée du module (généralement le point d'entrée ou la fonction principale de votre module) en augmentant l'objet "exports" de chaque module.

Ainsi, un "vrai" module CommonJS ressemble à ceci.

Déposer un:

// a.js

function doSomething() {
  console.log("I am doing something");
}

module.exports = doSomething

Fichier B:

// b.js

doSomething();
// Exception - attempt to call a non-existent function

Fichier C:

// c.js
var doSomething = require('a');
doSomething();
// logs "I am doing something"

Dans le navigateur qui n'a pas de portée de module, a.js augmenterait la portée globale avec la fonction doSomething, car elle est déclarée comme globale. Browserify contourne ce problème en encapsulant chaque module intégré dans un encapsuleur de fonction et en fournissant un objet "exports" aux modules inclus comme argument à cet encapsuleur.

Entrez AngularJS. Vous avez deux approches que vous pouvez utiliser ici, dont je suppose du fait que vous n'utilisez pas require ('angular') est la première:

  1. Incluez AngularJS en tant que script codé en dur disponible dans votre index.html avant votre script de bundle transposé par Browserify.
  2. Shim AngularJS pour qu'il soit attaché à un objet exports plutôt qu'à la fenêtre (en utilisant quelque chose comme browserify-shim ), puis en l'important en utilisant require comme tout autre module.

J'ai tendance à préférer la deuxième approche, car il est assez étrange d'utiliser Browserify pour vous donner la portée du module, puis faire de la dépendance principale de votre projet une fenêtre globale.

Cependant, AngularJS possède déjà son propre système de modules pilotés par injection de dépendance. Lorsque vous déclarez des composants angularJS, vous les attachez à des objets de module qui eux-mêmes ont été attachés à l'objet angular. Cela signifie que l'objet exports pour vos fichiers de module angularJS est essentiellement redondant dans le cas d'Angular, car tant que le fichier s'exécute, l'objet angular sera augmenté avec votre module et vos composants.

Vous devez toujours "exiger" les fichiers car sinon Browserify ne les regroupera pas, ils ne s'exécuteront jamais et ils n'augmenteront jamais l'objet angular avec vos modules. Mais vous n'avez pas besoin d'ajouter quoi que ce soit aux exportations pour Angular, puisque l'objet angular est vos exportations.

Alors pourquoi ai-je passé tout ce temps à expliquer le fonctionnement des modules CommonJS et des exportations? Parce que nous espérons que l'autre raison pour laquelle vous utilisez Browserify est de vous permettre d'utiliser des modules hébergés sur NPM dans votre application de navigateur. La plupart de ces modules sont des modules commonJS non angulaires, ce qui signifie que leurs fonctionnalités sont exposées via une exportation. Dans ce cas, il est important de capturer leurs exportations dans une variable lorsque vous en avez besoin, comme je le fais dans c.js au dessus. De même, si vous écrivez des modules et les libérez dans NPM, vos utilisateurs s'attendent à ce que vous ajoutiez le point d'entrée à votre module à l'objet exports du fichier déclaré comme principal dans votre package.json.

32
HowlingEverett