← Назад к вопросам

Что такое CommonJS-модуль?

1.0 Junior🔥 141 комментариев
#Node.js и JavaScript

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI29 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое CommonJS-модуль?

CommonJS — это спецификация для модульной системы JavaScript, которая позволяет разбивать код на отдельные файлы (модули) и переиспользовать их в разных частях приложения. CommonJS — это стандарт для Node.js и был основной системой модулей до появления ES6 модулей.

История и контекст

До CommonJS, JavaScript не имел встроенной системы модулей. Все скрипты загружались глобально в браузер, что приводило к:

  • Загрязнению глобального scope (все переменные видны везде)
  • Конфликтам имен (если два скрипта объявляют переменную с одинаковым именем)
  • Сложности управления зависимостями

CommonJS решил эту проблему для серверного JavaScript (Node.js).

Основные концепции

1. Экспорт модуля (module.exports)

Модуль может экспортировать (делиться) свой код с другими модулями через module.exports:

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

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

// Экспортируем объект с функциями
module.exports = {
  add,
  subtract
};

Или простой экспорт:

// logger.js
module.exports = function log(message) {
  console.log(`[LOG] ${message}`);
};

2. Импорт модуля (require)

Другие файлы могут импортировать модуль через функцию require():

// main.js
const math = require("./math");
const log = require("./logger");

console.log(math.add(5, 3));      // 8
console.log(math.subtract(10, 4)); // 6
log("Application started");         // [LOG] Application started

3. Структура модуля

Каждый CommonJS модуль имеет доступ к:

// module.js
console.log(module);       // Объект текущего модуля
console.log(module.id);    // ID модуля (обычно путь к файлу)
console.log(module.exports); // То, что экспортируется
console.log(exports);      // Ссылка на module.exports
console.log(__filename);   // Полный путь к файлу
console.log(__dirname);    // Папка файла
console.log(require);      // Функция для импорта

Практические примеры

Пример 1: Простая функция

// utils/string.js
module.exports = {
  toUpperCase: (str) => str.toUpperCase(),
  toLowerCase: (str) => str.toLowerCase(),
  capitalize: (str) => str.charAt(0).toUpperCase() + str.slice(1)
};

// app.js
const string = require("./utils/string");
console.log(string.capitalize("hello")); // Hello

Пример 2: Класс или конструктор

// models/User.js
class User {
  constructor(name, email) {
    this.name = name;
    this.email = email;
  }
  
  getInfo() {
    return `${this.name} (${this.email})`;
  }
}

module.exports = User;

// app.js
const User = require("./models/User");
const user = new User("John", "john@example.com");
console.log(user.getInfo()); // John (john@example.com)

Пример 3: Конфигурация

// config.js
module.exports = {
  app: {
    port: 3000,
    host: "localhost"
  },
  database: {
    url: "postgresql://localhost/mydb",
    pool: { max: 10 }
  },
  jwt: {
    secret: process.env.JWT_SECRET || "your-secret-key",
    expires: "7d"
  }
};

// server.js
const config = require("./config");
const express = require("express");

const app = express();
app.listen(config.app.port, config.app.host);

Пример 4: Middleware в Express

// middleware/auth.js
module.exports = (req, res, next) => {
  const token = req.headers.authorization?.split(" ")[1];
  
  if (!token) {
    return res.status(401).json({ error: "No token" });
  }
  
  req.user = verifyToken(token);
  next();
};

// server.js
const express = require("express");
const auth = require("./middleware/auth");

const app = express();
app.use(auth); // Использование middleware
app.get("/profile", (req, res) => {
  res.json(req.user);
});

Важные различия между exports и module.exports

// ⚠️ Важно понимать разницу

// Способ 1: Добавление к module.exports
module.exports.add = (a, b) => a + b;
module.exports.subtract = (a, b) => a - b;

// Способ 2: Переопределение module.exports
module.exports = {
  add: (a, b) => a + b,
  subtract: (a, b) => a - b
};

// ❌ ОПАСНО: exports перестанет работать
exports.multiply = (a, b) => a * b;
module.exports = { divide: (a, b) => a / b };
// multiply не будет экспортирован!

Кэширование модулей

Важная особенность: Node.js кэширует модули. При первом require() модуль загружается и выполняется, затем результат кэшируется. Последующие require() возвращают кэшированный объект:

// counter.js
let count = 0;

module.exports = {
  increment: () => ++count,
  getCount: () => count
};

// test.js
const counter1 = require("./counter");
const counter2 = require("./counter");

counter1.increment();
console.log(counter1.getCount()); // 1
console.log(counter2.getCount()); // 1 (ОДИН И ТОТ ЖЕ ОБЪЕКТ!)

console.log(counter1 === counter2); // true

Это означает, что состояние модуля сохраняется между импортами.

Пути к модулям

// Относительный путь
const utils = require("./utils");        // ./utils.js или ./utils/index.js
const config = require("../config");     // выше на один уровень

// Абсолютный путь
const math = require("/home/user/app/math");

// NPM пакеты (node_modules)
const express = require("express");      // поиск в node_modules
const _ = require("lodash");             // внешний пакет

// Явное расширение
const myModule = require("./myModule.js");

Сравнение с ES6 модулями

АспектCommonJSES6 Module
Экспортmodule.exportsexport / export default
Импортrequire()import
СинхронностьСинхронныйАсинхронный
КэшированиеДаДа
БраузерНетДа
Node.jsНативноНужен флаг --experimental-modules

Современное использование

Сегодня в Node.js:

  • CommonJS — по умолчанию в .js файлах
  • ES6 modules — в .mjs файлах или если "type": "module" в package.json
{
  "name": "my-app",
  "version": "1.0.0",
  "type": "module"
}
// Теперь можно использовать ES6 синтаксис
import express from "express";
import { add, subtract } from "./math.js";

export function myFunction() { ... }

Итоги

CommonJS модуль — это:

  • Самостоятельный файл с кодом
  • Экспортирует данные через module.exports
  • Импортирует другие модули через require()
  • Кэшируется Node.js
  • Синхронный (в отличие от ES6 модулей)
  • Стандарт для Node.js последние 15+ лет

CommonJS остается важной частью экосистемы Node.js и должен быть хорошо понят каждым backend разработчиком.