I am Hack Sparrow
Captain of the Internets.

Node.js Module – exports vs module.exports

What is the difference between exports and module.exports in Node.js?

You must be familiar with the exports object in Node.js modules, using which you create functions in your modules like this (assume in a file named rocker.js):

exports.name = function() {
console.log('My name is Lemmy Kilmister');

which you call from another file thus:

var rocker = require('./rocker.js');
rocker.name(); // 'My name is Lemmy Kilmister'

But what the heck is module.exports? Is it even legal?

Here is an eye-opener - module.exports is the real deal. exports is just module.exports's little helper. Your module returns module.exports to the caller ultimately, not exports. All exports does is collect properties and attach them to module.exports IF module.exports doesn't have something on it already. If there's something attached to module.exports already, everything on exports is ignored.

Put the following in rocker.js:

module.exports = 'ROCK IT!';
exports.name = function() {
console.log('My name is Lemmy Kilmister');

And this in another file, and run it:

var rocker = require('./rocker.js');
rocker.name(); // TypeError: Object ROCK IT! has no method 'name'

The rocker module completely ignored exports.name, and returned a string 'ROCK IT!'. From that you probably realize that your modules don't always have to be 'module instances'. Your modules can be any legal JavaScript object - boolean, number, date, JSON, string, function, array, and so on. Your module is whatever you set module.exports to. If you don't set module.exports to anything explicitly, the properties of exports and attached to it and returned.

In this case, your module is a class:

module.exports = function(name, age) {
this.name = name;
this.age = age;
this.about = function() {
console.log(this.name +' is '+ this.age +' years old');

and you'd use it this way:

var Rocker = require('./rocker.js');
var r = new Rocker('Ozzy', 62);
r.about(); // Ozzy is 62 years old

In this case, your module is an array:

module.exports = ['Lemmy Kilmister', 'Ozzy Osbourne', 'Ronnie James Dio', 'Steven Tyler', 'Mick Jagger'];

and you may use it this way:

var rocker = require('./rocker.js');
console.log('Rockin in heaven: ' + rocker[2]); //Rockin in heaven: Ronnie James Dio

So you get the point now - if you want your module to be of a specific object type, use module.exports; if you want your module to be a typical module instance, use exports.

The result of attaching properties to module.exports is akin to attaching properties to exports. For example this:

module.exports.name = function() {
console.log('My name is Lemmy Kilmister');

does the same thing as:

exports.name = function() {
console.log('My name is Lemmy Kilmister');

But note that, they are not the same thing. As I said earlier module.exports is the real deal, exports is just its little helper. Having said that, exports is the recommended object unless you are planning to change the object type of your module from the traditional 'module instance' to something else.

I hope this post helped you understand the difference between exports and module.exports, and learn a bit more about how modules work in Node.js. Any questions, ping me in the comments.

UPDATE: 7th Feb, 2014

As long are you don't overwrite the module.exports object with an assignment operation, anything attached to module.exports and exports will be available in the 'required' module.

If this is the content of your module:

module.exports.age = 68;
exports.name = 'Lemmy Kilmister';

The following code would work fine:

var rocker = require('./rocker.js');
console.log('%s is %s', rocker.name, rocker.age); // Lemmy Kilmister is 68


if you overwrite module.exports with anything in your module, it will fail:

module.exports = 'LOL';
module.exports.age = 68;
exports.name = 'Lemmy Kilmister';


module.exports.age = 68;
exports.name = 'Lemmy Kilmister';
module.exports = 'WTF';

the order doesn't matter, rocker.age and rocker.name will now be undefined.

Also, note: just because module.exports.age and exports.name are exported, does not mean you should use a combination of both. My recommendation is to stick to exports.*, and be aware of module.exports.*.

34 Responses to “Node.js Module – exports vs module.exports”

  1. Walt Williams says:

    How about returning an array from a module? I am performing a query on a MongoDB to get a list of users based on a group id. That list is then stored in an array which I would like to pass back to the callers of the module.

  2. krishnad says:

    Very nice explanation good tutorial helped me lot thanks bro

  3. karthik says:

    I created a file global_var.js as below:
    module.exports = {
    some_obj : {}
    I am updating some_obj values frequently in another files by the below process:

    var globalVar = require(‘./global_var.js’);
    globalVar.some_obj[“some_key”]=”some value”;

    but sometime it in not updating or overwrite previous values.

    For this purpose which is the better way for global variables/objects in between exports & module-exports ?

  4. Idaho says:

    Glad I ended up here with beautiful explanation after all those hassles i made trying to figure out what they are and makes difference between those two. Thanks!

Make a Comment