The Module System in Javascript

srishtikprasad

Srishti Prasad

Posted on May 26, 2024

The Module System in Javascript

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.

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

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

module.exports = {
    add,
    subtract
};
Enter fullscreen mode Exit fullscreen mode

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.

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

exports.subtract = function(a, b) {
    return a - b;
};
Enter fullscreen mode Exit fullscreen mode

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.

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

module.exports = {
    verbose,
    logger
};
Enter fullscreen mode Exit fullscreen mode

Exporting functions

function verbose(){
console.log("verbose")
}
module.exports = verbose
Enter fullscreen mode Exit fullscreen mode

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.

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')); 
Enter fullscreen mode Exit fullscreen mode

Exporting Instances

Instead of exporting a class, you can export an instance of the class, ensuring there is a single shared instance.

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'));
Enter fullscreen mode Exit fullscreen mode

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
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.

💖 💪 🙅 🚩
srishtikprasad
Srishti Prasad

Posted on May 26, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related