NodeJS - module.exports vs exports

— 4 minute read

I read an article on the difference between module.exports and exports in NodeJS and thought I could contribute to the discussion.

The key difference between the two is that module.exports is what matters, and exports just happens to point to the same thing.

It might help clarify things to show how the two variables are initialized. Essentially before your code runs, there is code that runs like this:

var module = {…}; // other module stuff
var exports = module.exports = {};

So both variables initially point to the same empty Object, but of course can be reassigned to any other value instead. If you reassign the exports variable, it doesn’t affect module.exports. Similarly, if you reassign module.exports, it no longer affects exports. They will be pointing at different values.

It's important to note the distinction between variables and values. module.exports and exports are just variables that start out pointing to the same value. If you modify the value they both point to, for example if that value is an object and you set properties on it, then both of those variables are both affected. But if you point one of those variables at a different value, then modifying the value of one will no longer change the other.

What makes module.exports the “real deal” is that when someone require()s your module, require executes something like this:

function require(moduleName) {
var module = getModule(moduleName);
return module.exports;
}

require grabs the module and finds the exports property of it. So the values that matter are first whatever value module points to, and then whatever value the exports property on it points to.

It might also help to say that module is the real deal, not that module.exports is. Take this code for example:

var truth = module;
var notExports = module.exports;

truth.exports = { genre: "Rock" };
notExports.genre = "Blues";

Rock will be exported. Since truth is pointing to module, it can make lasting changes to the exports that notExports can’t. As soon as truth changes the value of module's exports property, the old value that notExports still points to is moot.