start learning
Image 1

JavaScript Module systems

JAVASCRIPT MODULE SYSTEMS are mechanisms used in JavaScript to organize and encapsulate code into modular units. Modules allow developers to break down their code into smaller, more manageable pieces, improving code organization, reusability, and maintainability.

There are several module systems available in JavaScript, including the following :
Modules only work with an HTTP(s) protocol. A web-page opened via the file:// protocol cannot use import / export.


CommonJS

CommonJS is a module system primarily used in server-side JavaScript, popularized by Node.js. It relies on the require function to import modules and the module.exports or exports object to export values from a module. CommonJS modules have a synchronous nature, meaning that module dependencies are resolved at runtime.

Module Definition (myModule.js)


// Exporting module with properties 'foo' and 'bar'
module.exports = {
  foo: 'Hello',
  bar: 'World'
};

In this step, we define a module using CommonJS syntax. The module.exports object is assigned with an object that has two properties: foo and bar with their respective values.

Module Import (main.js)


// Importing module
const myModule = require('./myModule');

// Log the 'foo' property of 'myModule'
console.log(myModule.foo); // Output: Hello

Here, we import the module myModule using the require function, providing the path to the module file ('./myModule'). The imported module is assigned to the variable myModule, and we can access its properties (foo in this case) and log its value to the console.


AMD (Asynchronous Module Definition)

AMD is a module system designed for browser-based JavaScript applications that require asynchronous loading of modules. It utilizes the define function to declare modules and the require function to import dependencies. AMD modules can be loaded dynamically and asynchronously, improving performance.

Module Definition (myModule.js)


define(['dependency1', 'dependency2'], (dep1, dep2) => {
  // Return an object with properties 'foo' and 'bar' based on dependencies
  return {
    foo: dep1,
    bar: dep2
  };
});

In this step, we define a module using AMD syntax. The define function is used to declare the module. It takes an array of dependencies (['dependency1', 'dependency2']) and a callback function that receives the resolved dependencies as arguments (dep1 and dep2). Inside the callback, we return an object with properties foo and bar, assigned with the resolved dependencies.

Module Import (main.js)


require(['myModule'], (myModule) => {
  // Log the 'foo' property of 'myModule'
  console.log(myModule.foo); // Output: Hello
});

Here, we import the module myModule using the require function, passing an array with the module name (['myModule']) and a callback function. Once the module is loaded and dependencies are resolved, the callback function is executed, and the resolved module is available as an argument (myModule). We can access its properties (foo in this case) and log its value to the console.


ES Modules (ESM)

ES Modules are a standardized module system introduced in ECMAScript 6 (ES6) and supported in modern JavaScript environments, both in servers and browsers.
ES Modules use the import and export keywords to declare and consume modules. They have a static nature, allowing static analysis and optimization during bundling and compilation processes.

Module Definition (myModule.js)


export const foo = 'Hello';
export const bar = 'World';

In this step, we define a module using ES module syntax. The export keyword is used to export values from the module. We export two constants, foo and bar, with their respective values.

Module Import (main.js)


import { foo, bar } from './myModule.js';

// Log the 'foo' variable
console.log(foo); // Output: Hello

Here, we import specific values (foo and bar) from the module myModule.js using the import keyword. We provide the path to the module file ('./myModule.js') and specify the values we want to import within curly braces. Once imported, we can access and log the value of foo to the console.


ES Modules (ESM)

UMD modules typically involve a conditional check to determine the module system in use and handle the exports and imports accordingly. The following is a simplified example of a UMD module

Module Definition (myModule.js)


// Create an immediately-invoked function expression (IIFE)
((root, factory) => {
  if (typeof define === 'function' && define.amd) {
    // AMD module definition
    define(['dependency1', 'dependency2'], factory);
  } else if (typeof module === 'object' && module.exports) {
    // CommonJS module definition
    module.exports = factory(require('dependency1'), require('dependency2'));
  } else {
    // Global variable (no module system)
    root.myModule = factory(root.dependency1, root.dependency2);
  }
})(typeof self !== 'undefined' ? self : this, (dep1, dep2) => {
  // Module implementation
  return {
    foo: dep1,
    bar: dep2
  };
}));

The examples above showcase the basic syntax and usage of each module system. However, please note that the actual implementation and usage might vary depending on the specific JavaScript environment and build tools you are using in your project.

The UMD module system doesn't have a specific step-by-step example because it involves a more complex setup to handle compatibility with different module systems. The provided UMD example is a generic structure that adapts to the module system in use (AMD, CommonJS, or global variable).


Please note that the UMD example is a generic template, and the actual implementation may vary depending on the specific requirements of your project and the module system you intend to support.