Understanding the tricky module.exports and exports in Node.js

What is a Module?

A module is a separate program file in Node.js. When creating a module, it can be classified as a grouping of all related functions into a file.

Purpose of a Module

Keeping all functional programs in a single file is really hard to maintain and deal with during the development. Having the code split up into multiple accessible files allows us to have appropriate file names for every file. This way you can easily identify the module and know where to find it at times of need. Having modules makes it easier to find certain parts of code which makes it more maintainable.

Most common Module Formats

There are many module formats in JavaScript but there are two formats that used almost in all javascript projects:

  • The CommonJS (CJS) format is used in Node.js and uses require and module.exports to define dependencies and modules. The npm ecosystem is built upon this format.
  • The ES Module (ESM) format. As of ES6 (ES2015), JavaScript supports a native module format. It uses an export keyword to export a module’s public API and an import keyword to import it.

What we will talk about in this article is related to CommonJS format

Requiring a Module

Node.js comes with a set of built-in modules that we can use in our code without having to install them. To do this, we need to require the module using the require keyword and assign the result to a variable.

you can use the file system module and its readdir method:

fs.readdir(folderPath, (err, files) => {
files.forEach(file => {

Note that in CommonJS, modules are loaded synchronously and processed in the order they occur.

Creating and Exporting a Module

create our own module and export it for use elsewhere in our program.

The other module is index.js

Exporting Multiple Methods and Values

We can export multiple methods and values in the same way:


Notice how the name we give the exported dateOfBirth variable can be anything we fancy (dob in this case). It doesn’t have to be the same as the original variable name.

Variations in Syntax

I should also mention that it’s possible to export methods and values as you go, not just at the end of the file. For example:

And thanks to destructuring assignment, we can cherry-pick what we want to import:

Exporting a Default Value

when you have a module that exports just one thing, it’s more common to use module.exports, but for sure you can use just `exports`:

module.exports = User;// index.js
const User = require('./user');
const jim = new User('Jim', 37, 'jim@example.com');

What’s the Difference Between module.exports and exports?

create file index.js and run it using node

the output:

So it looks like module is a contextual reference to the file you just executed.

Did you notice it has an exports property? Which is an empty object. That's where you define the 'importable' objects of your module.

Now edit index.js and run it again:

Module {
id: '.',
exports: { firstName: 'Ibrahim', lastName: 'AlRayyan' },

You can see that assigning properties to the exports object has added those properties to modules.exports.

That is because exports is a reference to modules.exports.

You can confirm it with the following code:

The output will be:

Let’s now explain the real difference between them by wring some codes in two separate files.

I’ll use two files user.js and index.js where index.js will never change:

  1. Uses onlyexports in exporting (source) file → user.js :

The output will be:

  1. Uses both exports and module.exports in the same source file:

The output will be:

So, using module.exports and exports in the same file overrides the value of exports. And should not use both of them in the same file or module.

Other useful things to know

When the require() function is called to the same module in multiple files, the module has to be loaded once only. Next time a require() function is called on the same module then pulls from the cache.
The require() function loads modules synchronously. Suppose, it loads modules asynchronously, we could not access the objects in the right way. So, synchronous behavior is required while requiring modules from one file to another.

I hope you have found this useful. You can start to test these code snippets to get a clear understanding of this concept.


  1. https://www.sitepoint.com/understanding-module-exports-exports-node-js/
  2. https://www.hacksparrow.com/nodejs/exports-vs-module-exports.html
  3. https://www.agiratech.com/blog/understanding-module-exports-and-exports-in-node-js/

React Developer, Mobile cross-platform developer, JavaScript Lover

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store