Nodejs module, module.exports and exports

Introduction

With the increase in application requests, which also increases the amount of code that has to be written, it was no longer practical having all code in one file. The concept of modulation was born, which allowed us to separate our files into different modules, keeping our code base clean, small, and organized.

Modules

Every file that is created in nodejs is treated as a separate module, when a Javascript file is ran using nodejs a new module is created for it

We have three types of modules:

Core Modules: These are the built-in modules, nodejs provides eg http, fs, etc.

User Modules: These are the user-defined modules, locally created.

Node Modules: These are the modules created by others that are available through the NPM(Node package manager). The user can download the modules using npm install.

When we create a file, let's say greetings.js

function greetings(){
    return "Hello Goodmorning"
}

console.log(module)

The output of this will be

Module {
  id: '.',
  path: '/Users/john/Desktop/test',
  exports: {},
  filename: '/Users/john/Desktop/test/greetings.js',
  loaded: false,
  children: [],
  paths: [
    '/Users/john/Desktop/test/node_modules',
    '/Users/john/Desktop/node_modules',
    '/Users/john/node_modules',
    '/Users/node_modules',
    '/node_modules'
  ]
}

What are all these right, I will tell you.

id: This is a unique identifier for the module, in this case, the '.' indicates this is the main or entry point of the application.

path: This is the directory path of the module, it's the location where the module resides.

exports: This is the object that will be returned when this module is required in another module. right now it's an empty object because nothing has been exported, but more on that later.

filename: This is the full path of the module including its filename.

loaded: A boolean indicating whether a module has been required, which will change in the requiring modules object.

children: An array of modules that this module is dependent on, These are the modules that have been required in the code of the current module.

paths: This is the array of file paths Nodejs will search for the required modules, in the current modules, if it's not a core module or the file path is not indicated eg "./". Nodejs will use this hierarchy to search.

Module.Exports

Actually module.exports, but for the sake of subtitle, when a module is first created the exports is set to an empty object, like we say earlier in the return value of the console.log(module), until the module exports something.

module.exports.greetings = function greetings(){
    return "Hello, Good morning"
}

The output of the exports of the module object has changed, because we are exporting something, let's see

  exports: { greetings: [Function: greetings] },

This exports object is available to any module requiring this greetings module.

Exports

Also exports, but for the sake of subtitle, Think of export as an alias, a short form for exporting objects.

exports.greetings = function greetings(){
    return "Hello, Good morning"
}

we also get this output

exports: { greetings: [Function: greetings] },

Note this, exports is a reference to the module.exports object that is created, I am sure you are familiar with how objects work in javascript.


//first one
exports.greetings = function greetings(){
    return "Hello, Good morning"
}

//second one
exports = function countGreetings(){
    return "greeted once"
}

The first one adds a greeting property to the module.exports object is referencing, while the second one changes the object exports points to. This way only the first one is seen in the module.exports

 exports: { greetings: [Function: greetings] },

Also when you do this

exports.greetings = function greetings(){
    return "Hello, Good morning"
}

module.exports = function applaud(){
    return "Clapped"
}

This is the output

  exports: [Function: applaud],

The module.exports is now referencing a different object than the one exports is referencing. so be careful to not reassign values if that is not your intention.

Well, that was a lot of referencing, but if you understand how objects work in javascript you would get a hang of it.

Conclusion

modules, module.exports, and exports are used, for managing and maintaining large codes, enabling readability, code reusability, and abstraction. This has helped keep our codes clean and also prevented programmers from looking at files with 20,000 lines of code in one file, imagine that. Overall I encourage you to try out the examples and play around with them.