🟢 Node.js Q12 / 110

What is CommonJS?

AI-Powered Answer ✓ Answered

CommonJS is a module specification that dictates how modules are written and used in JavaScript environments, most notably in Node.js. It provides a way to encapsulate code into reusable units, manage dependencies, and prevent global namespace pollution, becoming the standard for server-side JavaScript development before the advent of ES Modules.

What is a Module System?

A module system is a mechanism that allows developers to organize code into separate, reusable files. Without modules, all code would typically reside in a single global scope, leading to naming conflicts, difficulty in managing dependencies, and reduced maintainability. CommonJS was created to address this need for modularity in server-side JavaScript applications.

Core Concepts: Exporting and Importing

CommonJS provides two primary constructs for module interaction: module.exports for exporting functionality and require() for importing it.

Exporting Modules

In a CommonJS module, you expose variables, functions, or objects to other modules by assigning them to module.exports. There's also an exports shorthand, which is initially a reference to module.exports. However, if you directly reassign exports (e.g., exports = { ... }), it breaks the reference, and module.exports remains unchanged. It is generally safer to assign properties to exports or directly reassign module.exports.

javascript
// my-module.js
const secretKey = 'super_secret_123';

function encrypt(data) {
  return `encrypted(${data})`;
}

function decrypt(data) {
  return `decrypted(${data})`;
}

module.exports = {
  encrypt,
  decrypt,
  version: '1.0.0'
};

// Alternative: Export a single value/function directly
// module.exports = encrypt;

Importing Modules

To bring the functionality from another CommonJS module into your current file, you use the global require() function. require() synchronously loads the specified module and returns the value of its module.exports.

javascript
// app.js
const myModule = require('./my-module');

const originalData = 'Hello World';
const encryptedData = myModule.encrypt(originalData);
console.log(encryptedData); // Output: encrypted(Hello World)

const decryptedData = myModule.decrypt(encryptedData);
console.log(decryptedData); // Output: decrypted(encrypted(Hello World))
console.log(myModule.version); // Output: 1.0.0

Key Characteristics

  • Synchronous Loading: Modules are loaded synchronously. This means that execution pauses until the required module is fully loaded and processed. This is generally acceptable in server-side environments where modules are loaded from the local file system.
  • Module Caching: Once a module is loaded via require(), Node.js caches its exports. Subsequent calls to require() for the same module path will return the cached instance, preventing redundant loading and ensuring that modules are singletons.
  • Local Scope: Each CommonJS module has its own private scope. Variables defined within a module are not accessible globally unless explicitly exported.
  • Server-Side Focus: CommonJS was primarily designed for server-side environments (like Node.js) and desktop applications, where network latency for module loading is not a primary concern, unlike web browsers.

CommonJS vs. ES Modules (ESM)

While CommonJS has been the cornerstone of modularity in Node.js, ECMAScript Modules (ESM), using import and export statements, are the official standard for JavaScript modules across all environments. ESM offers features like static analysis, tree-shaking, and asynchronous loading. Node.js supports both systems: CommonJS is used by default for .js files unless specified otherwise (e.g., in package.json with "type": "module"), while .mjs files are treated as ESM, and .cjs files are explicitly CommonJS.