Что такое CommonJS-модуль в Node.js?

«Что такое CommonJS-модуль в Node.js?» — вопрос из категории Node.js Core, который задают на 26% собеседований Node.js Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

CommonJS — это стандарт модульной системы, который был основным в Node.js до появления ES Modules. Он использует синхронную загрузку модулей и основан на функциях require() для импорта и module.exports/exports для экспорта.

Базовый пример:

// calculator.js
const add = (a, b) => a + b;
const multiply = (a, b) => a * b;

module.exports = {
  add,
  multiply
};

// или альтернативно:
exports.add = add;
exports.multiply = multiply;

// app.js
const calculator = require('./calculator');
console.log(calculator.add(5, 3)); // 8
console.log(calculator.multiply(4, 2)); // 8

Ключевые особенности CommonJS:

  • Синхронная загрузка: модули загружаются синхронно при первом вызове require()
  • Кэширование: модуль загружается только один раз, последующие вызовы require() возвращают кэшированный экземпляр
  • Циклические зависимости: поддерживаются, но могут вести себя неочевидно
  • module.exports vs exports: exports — это ссылка на module.exports, перезапись exports новой ссылкой нарушит экспорт

Пример циклической зависимости в CommonJS:

// a.js
console.log('a starting');
exports.done = false;
const b = require('./b.js');
console.log('in a, b.done =', b.done);
exports.done = true;
console.log('a done');

// b.js
console.log('b starting');
exports.done = false;
const a = require('./a.js');
console.log('in b, a.done =', a.done);
exports.done = true;
console.log('b done');

В современных Node.js-проектах я часто использую смешанный подход: CommonJS для конфигурационных файлов и утилит, а ES Modules для основного кода приложения.