The Module System in Javascript
Tags: javascript, webdev, beginners, programming
Published: 2024-05-26 15:18:21

In the ever-evolving landscape of JavaScript development, mastering the module system is crucial for creating scalable, maintainable, and efficient code, transforming how developers structure and share their projects across the modern web.

##Necessity of module system
1. **Code Organization**: Having a way to split the codebase into multiple files, modules help in organizing code into manageable, logical units. This makes the codebase easier to understand and maintain.
2. **Reusability**: Modules allow you to reuse code across different parts of an application or even across different projects.
3. **Encapsulation**: Modules encapsulate code, which means they expose only what is necessary and hide the internal details. This prevents unintended interactions and reduces bugs.
4. **Dependency Management**: A good module system should make it easy for module developer to build on top of existing modules.
Modules help in managing dependencies between different parts of the application, making it clear what functionality depends on what.

> **Module** - is actual unit of software that encapsulates related functionality

> **Module System** - on the other hand, is a set of rules, conventions, and mechanisms that enable the creation, importation, and use of modules within a programming language or environment. It defines how modules are written, organized, and accessed within an application example : CommonJS and ECMAScript Modules

## CommonJs Module system 
CommonJs is the first module system in Nodejs.CommonJs respects the CommonJs specification, with addition of some custom extensions.

- it uses the `require()` function to import modules.

- module.exports or exports are special variables that can be used to export public functionality from the current module.

> The require() function in CommonJS modules is **synchronous**. When you use require() to import a module, Node.js will load and execute the module **synchronously**, blocking the execution of the code until the required module is fully loaded and its exports are available.

## module.exports vs exports 

### Using module.exports 

is an object provided by Node.js for defining what a module exports. When you assign a value to `module.exports`, you are replacing the entire exports object with whatever value you provide.

```javascript
function add(a, b) {
    return a + b;
}

function subtract(a, b) {
    return a - b;
}

module.exports = {
    add,
    subtract
};
```
### Using exports 

`exports` is a shorthand reference to module.exports. Initially, exports is set to reference the same object as `module.exports`. You can use the exports object to add properties and methods to the exports object.

```javascript
exports.add = function(a, b) {
    return a + b;
};

exports.subtract = function(a, b) {
    return a - b;
};
```
##Module defination patterns
In Node.js, there are several popular patterns for defining and exporting modules. These include:

- named exports, 
- exporting functions,
- exporting classes,
- exporting instances, and 
- monkey patching

###**Named exports**
Uses module.exports or exports to export multiple values from a module.

```javascript
function verbose(name) {
    console.log("verbose");
}
const logger = "Goodbye!";

module.exports = {
    verbose,
    logger
};
```
###**Exporting functions**

```javascript
function verbose(){
console.log("verbose")
}
module.exports = verbose
```
Same pattern of export is followed in exporting class or an instance of class
Creating a class or an instance of class and exporting it using `module.export `


###**Exporting classes**
Modules can also export a class, which can then be instantiated by the importing code.
```javascript
class Greeter {
    constructor(greeting) {
        this.greeting = greeting;
    }
    greet(name) {
        return `${this.greeting}, ${name}`;
    }
}

module.exports = Greeter;

//Usage
const Greeter = require('./myClassModule');
const greeter = new Greeter('Hello');
console.log(greeter.greet('Charlie')); 
```
###**Exporting Instances**
Instead of exporting a class, you can export an instance of the class, ensuring there is a single shared instance.

```javascript
class Greeter {
    constructor() {
        this.greeting = 'Hello';
    }
    greet(name) {
        return `${this.greeting}, ${name}`;
    }
}

const greeterInstance = new Greeter();
module.exports = greeterInstance;

//Usage
const greeter = require('./myInstanceModule');
console.log(greeter.greet('Dana'));
```
`Reference Book : NodeJs Design pattern by Mario Casciaro ` 

This blog was mainly about module system and CommonJs module .
It is extremely important to understand ES Module ,in the next blog I'll cover specifically ES Module and compare both module. [ES Module](https://dev.to/srishtikprasad/es-module-50a)
Monkey patching is an important topic to learn will post separate blog on this. 
Let me know if you have any query,will try me best to address them all to the best of my knowledge.