Node.js — Modules

Understanding modules and require, exports, and module.exports

Harith Javed Bakhrani
4 min readMar 2, 2020
Node.js

If you have been developing applications using Node.js, then you must have used require and module.exports. But where do they come from and how do we understand them more? To answer this question, we need to first understand what a module is in Node.js.

What is a module?

A module is a file or folder that contains code. Yes, any file on your computer that contains Node.js code is known as a module.

Why call it a module?

Your next question might be, “why call it a module, when its just a file with some code?”

Node wraps each and every file in a function and passes it 5 arguments. To see these 5 arguments, we can use console.log:

console.log(arguments);

When we put the above code at the top-level of a file and run it via Node, we would see the 5 arguments printed out to the console. These five arguments are as follows: exports, module, require, __filename, __dirname

exports or module.exports is used to define an API of a module.

require is used to require other modules.

__filename contains the path to this file.

__dirname contains the path to the folder hosting this file.

NOTE: These are not global objects, they are arguments to the function that Node wraps around the code in a file before it gets executed by Node.

Now that we know that Node wraps each and every file with a function, we should also note that any top-level variable in this file is NOT global, it is scoped to the wrapping function.

Other than the function receiving 5 arguments, it also returns module.exports object. module object is used to manage dependencies and the APIs of modules.

So, in reality, if we have a file that contains one console.log statement:

console.log(arguments);

Node.js would turn the file to:

funtion(exports, module, require, __filename, __dirname) {
console.log(arguments);
return module.exports
}

require, exports, and module.exports

Now that we know where exactly require, exports and module.exports from, let us better understand each one of this and put it to use!

exports and module.exports are basically referring to the same object. At the end of each module, Node.js returns module.exports object which can be used in other modules by requiring a module.

require is used to require other modules in the current module you are working with. By requiring other modules, we are basically requiring their module.exports object.

To see require and exports object in action, let us create two files; answer.js and question.js. answer.js would contain an answer to the question asked in question.js file. Please note that I have created these two files just to demonstrate the use of theexports object and therequire method.

answer.js file — exporting answer constant
question.js file — requiring answer constant from answer.js file

As you can see that we are exporting the answer constant by making it part of theexports object (remember that Node wraps all the code in the file with a function which then returns module.exports object), and we are using it in the question.js by destructuring it from the object that we receive by requiring the answer.js file.

NOTE: Both of these files should be under one directory.

We can as well assign as many properties as we want to the exports object:

answer.js file
question.js file

What else can we export from a module? We can export anything we want; functions, lists, variables, basically anything which you can create with JS you can export it via module.exports.

By the way, here is the key difference between exports and module.exports; when you assign exports object directly as so: exports = 42 you would be breaking the assignment reference between exports and module.exports (in short, exports would NOT be the same as module.exports), and nothing would get returned because remember that at the end Node is returning module.exports and NOT exports. However, assigning module.exports directly works perfectly as expected:

Assigning module.exports object
Requiring answer.js file

Note that we don’t need to deconstruct the answer variable as we did before because this time we have altered the module.exports object and assigned it directly instead of adding a property to it.

To wrap this post up, let us see an example of exporting a function from a module as this is the most common way of utilizing modules:

Exporting a function from a module
Using a function from another module

Until next time, Adios my friends!

--

--

Harith Javed Bakhrani
Harith Javed Bakhrani

Written by Harith Javed Bakhrani

Muslim DevOps Engineer ready to learn and bring to life new and better ways of automating deployments and keeping them alive!

No responses yet