CommonJS проти ES Modules
1. Що таке CommonJS та ES Modules
| Модульна система | Де з'явилася | Ключова мета |
|---|---|---|
| CommonJS (CJS) | У Node.js (2009) | Дозволити використовувати модулі в серверному JavaScript |
| ES Modules (ESM) | У стандарті ECMAScript (ES6, 2015) | Створити нативну модульну систему для JS (браузери + Node.js) |
2. Синтаксис
CommonJS:
// math.js
const PI = 3.14;
function add(a, b) {
return a + b;
}
module.exports = { PI, add };
// main.js
const math = require('./math');
console.log(math.add(2, 3)); // 5Використовує:
require()- імпорт модулівmodule.exports/exports- експорт модулів
ES Modules:
// math.mjs
export const PI = 3.14;
export function add(a, b) {
return a + b;
}
// main.mjs
import { add } from './math.mjs';
console.log(add(2, 3)); // 5Використовує:
import/export- ключові слова стандарту ES6- Підтримується нативно браузером і Node.js (за правильного налаштування)
3. Головні відмінності
| № | Критерій | CommonJS (CJS) | ES Modules (ESM) |
|---|---|---|---|
| 1 | Синтаксис | require, module.exports | import, export |
| 2 | Завантаження модулів | Динамічне (під час виконання) | Статичне (під час парсингу) |
| 3 | Тип імпорту | Копія значення (by value) | Жива посилання (by reference) |
| 4 | Асинхронність | Синхронне завантаження | Асинхронне завантаження |
| 5 | Можливість "top-level await" | немає | є |
| 6 | Контекст this | this вказує на module.exports | this - undefined (строгий режим) |
| 7 | Кешування модулів | Так (одноразове завантаження) | Так, але з іншим механізмом |
| 8 | Підтримка в Node.js | За замовчуванням (.js) | Потрібно вказати "type": "module" або використовувати .mjs |
| 9 | Сумісність | Старі пакети (npm, Express тощо) | Новий стандарт ECMAScript |
| 10 | Використання в браузері | немає (тільки Node.js) | є (у <script type="module">) |
4. Статичне vs динамічне завантаження
-
CommonJS: Модуль завантажується під час виконання -
require()можна викликати будь-де:javascriptif (condition) { const utils = require('./utils'); } -
ES Modules: Імпорти статичні - мають бути на початку файлу:
javascriptimport utils from './utils.js'; // не можна всередині if
Це дозволяє ESM:
- робити tree-shaking (видаляти невикористовуваний код);
- оптимізувати збірку й виконання.
5. Живі посилання (Live Bindings)
ES Modules підтримують live bindings - якщо значення в модулі змінюється, імпорт теж оновлюється.
ESM:
// counter.mjs
export let count = 0;
export function increment() { count++; }
// main.mjs
import { count, increment } from './counter.mjs';
increment();
console.log(count); // 1 (оновилося)CJS:
// counter.js
let count = 0;
function increment() { count++; }
module.exports = { count, increment };
// main.js
const { count, increment } = require('./counter');
increment();
console.log(count); // 0 (копія значення)6. Підтримка в Node.js
CommonJS - увімкнено за замовчуванням
Файли .js вважаються CommonJS, якщо не вказано "type": "module".
ES Modules - потрібно явно увімкнути
Два способи:
- У
package.json:
{
"type": "module"
}→ тоді всі .js файли вважаються ESM.
2. Або використовувати розширення .mjs:
node main.mjs7. Приклад змішаного коду
Імпорт CommonJS з ESM:
// ESM
import pkg from './math.cjs';
console.log(pkg.add(2, 3));Імпорт ESM з CommonJS:
// CJS
(async () => {
const { add } = await import('./math.mjs');
console.log(add(2, 3));
})();Зверни увагу: у CJS імпорт ESM тільки асинхронний через import().
8. Контекст this і глобальні змінні
| Особливість | CommonJS | ES Modules |
|---|---|---|
this | Вказує на module.exports | undefined |
| Глобальні об'єкти | __dirname, __filename, require, module, exports | відсутні (можна імпортувати вручну через import.meta.url) |
9. Підтримка в npm-пакетах
- Старі пакети (
express,mongoose,chalk@4) - CommonJS. - Нові (
chalk@5,node-fetch,axios@next) - ES Modules.
При змішуванні часто виникають помилки:
Error [ERR_REQUIRE_ESM]: Must use import to load ES Module10. Підсумкова порівняльна таблиця
| Характеристика | CommonJS | ES Modules |
|---|---|---|
| Формат файлів | .js | .mjs / .js при "type": "module" |
| Імпорт | require() | import |
| Експорт | module.exports | export |
| Завантаження | Синхронне | Асинхронне |
| Тип зв'язку | Копія | Жива посилання |
Контекст this | module.exports | undefined |
| Браузери | немає | так |
| Tree-shaking | немає | так |
| Top-level await | немає | так |
| Сумісність | Старі пакети | Новий стандарт |
Коротко:
CommonJS - стара, синхронна, специфічна для Node.js система модулів. ES Modules - сучасний, стандартний і крос-платформний формат, що підтримується і Node.js, і браузерами.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.