NODEJS Contents

CommonJS (require/module.exports) in Legacy Code

Understand how CommonJS works in Node.js, why it became the default module system, and how it differs from ES Modules in real-world backend projects.

On this page

What Is CommonJS?

CommonJS (CJS) is the original Node.js module system. It uses require to import modules and module.exports to export values.

Basic Syntax

// math.js
function add(a, b) {
  return a + b;
}

module.exports = { add };

// index.js
const { add } = require('./math');
console.log(add(2, 3));

Why CommonJS Exists

When Node was created, JavaScript had no official module system. CommonJS solved the problem for server-side development years before ES Modules were standardized.

Synchronous Loading

CommonJS modules are loaded synchronously. This works well in Node because files are local and loading is fast.

Module Wrapper

Node wraps each CJS file in a function:

(function (exports, require, module, __filename, __dirname) {
  // your code here
});

This is why __dirname and __filename are available in CommonJS.

Exports vs module.exports

exports is a shortcut reference to module.exports. Reassigning exports breaks the link.

exports.value = 42; // correct

exports = {}; // wrong (does not export correctly)

CJS and ESM Differences

  • CJS uses require, ESM uses import
  • CJS loads synchronously, ESM is asynchronous
  • CJS allows dynamic require
  • ESM supports top-level await

Interoperability Issues

Importing CommonJS from ESM works, but named exports may not behave as expected because CJS exports a single object.

Dynamic Require

const moduleName = './math';
const math = require(moduleName);

This dynamic behavior is not supported in static ESM imports.

When to Use CommonJS

  • Legacy projects
  • Large existing ecosystems
  • Simpler backend setups

When to Avoid

  • New TypeScript-first projects
  • Shared browser + Node libraries

Production Insight

Many production systems still run on CommonJS. Understanding it is essential for debugging third-party packages and mixed-module environments.

Next Step

Next we will dive into module resolution and understand how Node decides which file to load when you import something.