Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the use of exports / module.exports?

Today I've adopting Browserify for my AngularJS project, but there is something that's very unclear to me. In all examples and blog posts I've seen stuff like this:

/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() {
    // ...
});

Sure, this works, but why do this? I've implemented it like this and that works absolutely fine too and feels more normal for an AngularJS project:

/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() {
    // ...
});

In other words, I'm completely skipping the exports/module.exports, only using require to basically include the files with the controllers, services, filter, etc.

Am I doing this right? I mean it all works, but am I going to be in trouble later on?

like image 298
Kevin Renskers Avatar asked Mar 18 '14 20:03

Kevin Renskers


People also ask

What is module exports used for?

Module exports are the instruction that tells Node. js which bits of code (functions, objects, strings, etc.) to “export” from a given file so other files are allowed to access the exported code.

What is exports and module exports?

The export statement is used in Javascript modules to export functions, objects, or primitive values from one module so that they can be used in other programs (using the 'import' statement). A module encapsulates related code into a single unit of code. All functions related to a single module are contained in a file.

What is the purpose of module export in node JS?

The main purpose of module. exports is to achieve modular programming. Modular programming refers to separating the functionality of a program into independent, interchangeable modules, such that each contains everything necessary to execute only one aspect of the desired functionality.

What does exports do in JavaScript?

The export declaration is used to export values from a JavaScript module. Exported values can then be imported into other programs with the import declaration or dynamic import.


1 Answers

The main (and honestly only) reason to use Browserify is if you want to have CommonJS modules (i.e. NodeJS modules) in the browser. A CommonJS module stays out of the global scope by having an implicit 'module' scope. You choose what to expose from the module scope (usually the entry point or primary function of your module) into by augmenting the 'exports' object that every module has.

So a 'real' CommonJS module looks like this.

File A:

// a.js

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

module.exports = doSomething

File B:

// b.js

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

File C:

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

In the browser which has no module scope, a.js would be augmenting the global scope with the doSomething function, since it's declared as a global. Browserify works around this by wrapping each bundled module into a function wrapper, and supplying an 'exports' object to the included modules as an argument to this wrapper.

Enter AngularJS. You've got two approaches you can use here, of which I'm assuming from the fact that you're not using require('angular') is the first:

  1. Include AngularJS as a hard-coded script available in your index.html before your Browserify-transpiled bundle script.
  2. Shim AngularJS so that it is attached to an exports object rather than the window (using something like browserify-shim), then importing it using require like any other module.

I tend to prefer the second approach because it's kind of weird to use Browserify to give you module scope and then make the major dependency of your project a window global.

However, AngularJS already has its own dependency-injection driven module system. When you declare angularJS components, you're attaching them to module objects which themselves have been attached to the angular object. This means that the exports object for your angularJS module files is essentially redundant in the case of Angular, since as long as the file executes then the angular object will be augmented with your module and components.

You still need to 'require' the files since otherwise Browserify won't bundle them, they'll never execute, and they'll never augment the angular object with your modules. But you don't need to add anything to the exports for Angular, since the angular object is your exports.

So why did I spend all this time explaining how CommonJS modules and exports work? Because hopefully the other reason why you are using Browserify is to allow you to make use of modules hosted on NPM in your browser application. Most of those modules are non-angular commonJS modules, meaning their functionality is exposed via an exports. In this case it's important to capture their exports in a variable when you require them, such as I'm doing in c.js above. Similarly, if you write some modules and release them to NPM, your users are going to expect you'll be adding the entry point to your module to the exports object of the file declared as main in your package.json.

like image 150
HowlingEverett Avatar answered Sep 30 '22 13:09

HowlingEverett