Module.Exports VS Exports in Node.Js

module.exports vs exports in Node.js

Setting module.exports allows the database_module function to be called like a function when required. Simply setting exports wouldn't allow the function to be
exported because node exports the object module.exports references. The following code wouldn't allow the user to call the function.

module.js

The following won't work.

exports = nano = function database_module(cfg) {return;}

The following will work if module.exports is set.

module.exports = exports = nano = function database_module(cfg) {return;}

console

var func = require('./module.js');
// the following line will **work** with module.exports
func();

Basically node.js doesn't export the object that exports currently references, but exports the properties of what exports originally references. Although Node.js does export the object module.exports references, allowing you to call it like a function.



2nd least important reason

They set both module.exports and exports to ensure exports isn't referencing the prior exported object. By setting both you use exports as a shorthand and avoid potential bugs later on down the road.

Using exports.prop = true instead of module.exports.prop = true saves characters and avoids confusion.

What is the difference between module.exports and exports.module in java script

module.exports is the property used to export values from a CommonJS module.

exports is a shorthand for module.exports.

exports.module is the same as module.exports.module which creates an value named module on the exported object.


So if you have:

module.exports = Product;

Then you would match it with:

const Product = require('./myModule');

But if you have:

exports.module = Product;

Then you would:

const myModule = require('./myModule');
const Product = myModule.module;

exports.module is, basically, a mistake and makes code confusing. Don't do that.

module.exports vs. export default in Node.js and ES6

The issue is with

  • how ES6 modules are emulated in CommonJS
  • how you import the module

ES6 to CommonJS

At the time of writing this, no environment supports ES6 modules natively. When using them in Node.js you need to use something like Babel to convert the modules to CommonJS. But how exactly does that happen?

Many people consider module.exports = ... to be equivalent to export default ... and exports.foo ... to be equivalent to export const foo = .... That's not quite true though, or at least not how Babel does it.

ES6 default exports are actually also named exports, except that default is a "reserved" name and there is special syntax support for it. Lets have a look how Babel compiles named and default exports:

// input
export const foo = 42;
export default 21;

// output
"use strict";

Object.defineProperty(exports, "__esModule", {
value: true
});
var foo = exports.foo = 42;
exports.default = 21;

Here we can see that the default export becomes a property on the exports object, just like foo.

Import the module

We can import the module in two ways: Either using CommonJS or using ES6 import syntax.

Your issue: I believe you are doing something like:

var bar = require('./input');
new bar();

expecting that bar is assigned the value of the default export. But as we can see in the example above, the default export is assigned to the default property!

So in order to access the default export we actually have to do

var bar = require('./input').default;

If we use ES6 module syntax, namely

import bar from './input';
console.log(bar);

Babel will transform it to

'use strict';

var _input = require('./input');

var _input2 = _interopRequireDefault(_input);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

console.log(_input2.default);

You can see that every access to bar is converted to access .default.

Difference between module.exports and exports in the CommonJs Module System

module is a plain JavaScript object with an exports property. exports is a plain JavaScript variable that happens to be set to module.exports.
At the end of your file, node.js will basically 'return' module.exports to the require function. A simplified way to view a JS file in Node could be this:

var module = { exports: {} };
var exports = module.exports;

// your code

return module.exports;

If you set a property on exports, like exports.a = 9;, that will set module.exports.a as well because objects are passed around as references in JavaScript, which means that if you set multiple variables to the same object, they are all the same object; so then exports and module.exports are the same object.

But if you set exports to something new, it will no longer be set to module.exports, so exports and module.exports are no longer the same object.

What is the difference between module.export and export

First of all it's exports and module.exports and not export and module.export (there is also an export keyword in JavaScript but it is not supported in Node yet).

Every Node module is wrapped with this function:

(function (exports, require, module, __filename, __dirname) {
// Your module code actually lives in here
});

See: https://nodejs.org/api/modules.html#modules_the_module_wrapper

Your module doesn't return the exported object from that functions as some people think. It can only pass data to the caller by adding properties to the arguments provided.

module.exports and exports are initially the same object - but it is module.exports that is actually exported if they end up to be not the same object.

It means that this will work the same:

module.exports.x = 1;
# or:
exports.x = 1;

because it changes the property of the same object.

But this will not be the same:

module.exports = {x: 1};

as this:

exports = {x: 1};

The last one will not export the x because it will substitute the object in exports (that was originally the same object as module.exports) while leaving the default empty object in module.exports to be actually exported.

The module.exports = {x: 1}; also substitutes a new object but it puts it where it needs to be to actually get exported. Note that this instruction changes the property of the module object, which can be seen by the caller after the implicit function that your module is wrapped in returns.

Now this would work:

exports = {x: 1};
module.exports = exports;

because it substitutes the object in exports with a new one but it also puts it into module.exports.

Remember that it is always module.exports that matters at the end if you didn't substitute one of them with a new object then you can use them interchangeably when setting their attributes:

exports.x = 1;
module.exports.y = 2;

For more info see this answer:

  • Why we use exports in nodejs?


Related Topics



Leave a reply



Submit