Even though the question has been answered and accepted long ago, I just want to share my 2 cents.
You can imagine that at the very beginning of your file there is something like (just for explanation):
var module = new Module(...);
var exports = module.exports;

So whatever you do just keep in mind that module.exports and NOT exports will be returned from your module when you're requiring that module from somewhere else.
So when you do something like:
exports.a = function() {
console.log("a");
}
exports.b = function() {
console.log("b");
}
You are adding 2 functions a and b to the object to which module.exports points, so the typeof the returning result will be an object : { a: [Function], b: [Function] }
Of course, this is the same result you will get if you are using module.exports in this example instead of exports.
This is the case where you want your module.exports to behave like a container of exported values. Whereas, if you only want to export a constructor function then there is something you should know about using module.exports or exports. Recall that module.exports will be returned when you require something, not exports.
module.exports = function Something() {
console.log('bla bla');
}
Now typeof returning result is 'function' and you can require it and immediately invoke it like:
var x = require('./file1.js')(); because you overwrite the returning result to be a function.
However, using exports you can't use something like:
exports = function Something() {
console.log('bla bla');
}
var x = require('./file1.js')(); //Error: require is not a function
Because with exports, the reference no longer points to the object where module.exports points, so there is not a relationship between exports and module.exports anymore. In this case module.exports still points to the empty object {} which will be returned.
The accepted answer from another topic should also help: Does JavaScript pass by reference?
Answer from Srle on Stack Overflowjavascript - module.exports vs exports in Node.js - Stack Overflow
What is "module.exports"?
module.exports best practices?
javascript - Difference between "module.exports" and "exports" in the CommonJs Module System - Stack Overflow
Videos
Even though the question has been answered and accepted long ago, I just want to share my 2 cents.
You can imagine that at the very beginning of your file there is something like (just for explanation):
var module = new Module(...);
var exports = module.exports;

So whatever you do just keep in mind that module.exports and NOT exports will be returned from your module when you're requiring that module from somewhere else.
So when you do something like:
exports.a = function() {
console.log("a");
}
exports.b = function() {
console.log("b");
}
You are adding 2 functions a and b to the object to which module.exports points, so the typeof the returning result will be an object : { a: [Function], b: [Function] }
Of course, this is the same result you will get if you are using module.exports in this example instead of exports.
This is the case where you want your module.exports to behave like a container of exported values. Whereas, if you only want to export a constructor function then there is something you should know about using module.exports or exports. Recall that module.exports will be returned when you require something, not exports.
module.exports = function Something() {
console.log('bla bla');
}
Now typeof returning result is 'function' and you can require it and immediately invoke it like:
var x = require('./file1.js')(); because you overwrite the returning result to be a function.
However, using exports you can't use something like:
exports = function Something() {
console.log('bla bla');
}
var x = require('./file1.js')(); //Error: require is not a function
Because with exports, the reference no longer points to the object where module.exports points, so there is not a relationship between exports and module.exports anymore. In this case module.exports still points to the empty object {} which will be returned.
The accepted answer from another topic should also help: Does JavaScript pass by reference?
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.
Im using MongoDB + Mongoose and you need to use:
const ExampleSchema = new mongoose.Schema({
title: example_title
})
module.exports = mongoose.model("List", ExampleSchema);What is module.exports? Why is it "exportS" instead of "export"? Is it a completely different thing than normal export? What happens if I did:
export default mongoose.model("List", ExampleSchema);instead? I wouldn't know to use "module.exports" if I didn't come across it in a tutorial.
When are you supposed to use it? How do you know when it's necessary?
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;, the result is exactly the same as module.exports.a = 9. This is because objects are passed around as references in JavaScript and both exports and module.exports refer to the same object as long as you don't reassign one of them to a different object.
The latter is what happens if you set exports to something new. It will no longer point to the same object as module.exports, and since only module.exports is returned to require, whatever you set exports to is not.
Renee's answer is well explained. Addition to the answer with an example:
Node does a lot of things to your file and one of the important is WRAPPING your file. Inside nodejs source code "module.exports" is returned. Lets take a step back and understand the wrapper. Suppose you have
greet.js
var greet = function () {
console.log('Hello World');
};
module.exports = greet;
the above code is wrapped as IIFE(Immediately Invoked Function Expression) inside nodejs source code as follows:
(function (exports, require, module, __filename, __dirname) { //add by node
var greet = function () {
console.log('Hello World');
};
module.exports = greet;
}).apply(); //add by node
return module.exports; //add by node
and the above function is invoked (.apply()) and returned module.exports. At this time module.exports and exports pointing to the same reference.
Now, imagine you re-write greet.js as
exports = function () {
console.log('Hello World');
};
console.log(exports);
console.log(module.exports);
the output will be
[Function]
{}
the reason is : module.exports is an empty object. We did not set anything to module.exports rather we set exports = function()..... in new greet.js. So, module.exports is empty.
Technically exports and module.exports should point to same reference(thats correct!!). But we use "=" when assigning function().... to exports, which creates another object in the memory. So, module.exports and exports produce different results. When it comes to exports we can't override it.
Now, imagine you re-write (this is called Mutation) greet.js (referring to Renee answer) as
exports.a = function() {
console.log("Hello");
}
console.log(exports);
console.log(module.exports);
the output will be
{ a: [Function] }
{ a: [Function] }
As you can see module.exports and exports are pointing to same reference which is a function. If you set a property on exports then it will be set on module.exports because in JS, objects are pass by reference.
Conclusion is always use module.exports to avoid confusion. Hope this helps. Happy coding :)