Модули: ESM и CommonJS
↑ 1.4 JavaScript: основы · ← Предыдущая
Зачем это на собесе
Различия форматов модулей и «живых» привязок; важно для сборки и Node.js.
Объяснение
| ESM (ES Modules) | CommonJS | |
|---|---|---|
| Синтаксис | import/export | require/module.exports |
| Загрузка | статический анализ, асинхронная | динамическая, синхронная |
| Привязки | «живые» (live bindings) | копия значения на момент require |
| Tree shaking | возможен | затруднён |
| Строгий режим | всегда | нет |
| Top-level await | да | нет |
this на верхнем уровне | undefined | module.exports |
| Браузер | нативно (type="module") | нет (нужна сборка) |
// math.js
export const PI = 3.14;
export function sum(a, b) { return a + b; }
export default class Calc {}
// app.js
import Calc, { PI, sum as add } from "./math.js";
import * as math from "./math.js";
const { heavy } = await import("./heavy.js"); // динамический импорт → код-сплиттинг
export { add }; // реэкспорт: export { x } from "./x.js";// CommonJS
const fs = require("node:fs");
module.exports = { read };Особенности ESM: импорты «поднимаются», выполняются один раз (кэш модулей), циклические зависимости разрешаются через живые привязки; пути с расширением (./a.js) в браузере и Node.
Сборщики (Vite, webpack, Rollup, esbuild) объединяют модули, выполняют tree shaking, code splitting. Пакеты: поля type, exports, main, module в package.json.
Нюансы и подводные камни
- Смешение ESM и CJS:
requireESM-модуля недоступно, нуженimport();__dirnameотсутствует в ESM (import.meta.url). - Побочные эффекты при импорте (код на верхнем уровне) выполняются один раз.
- Tree shaking требует чистых модулей и
sideEffects: falseвpackage.json. - Именованные и default-экспорты: default затрудняет переименование и автодополнение.
- Циклические зависимости приводят к
undefinedили TDZ.
Практика
- Разделите скрипт на модули и подключите как
type="module". - Выделите тяжёлую часть в динамический
import()и посмотрите чанк в Network. - Найдите циклическую зависимость через
madge.
Вопросы с ответами
Чем ESM отличается от CommonJS?
ESM — статические импорты и живые привязки, асинхронная загрузка; CJS — динамический
requireи копия значений.
Что такое tree shaking?
Удаление неиспользуемых экспортов при сборке; работает благодаря статической структуре ESM.