ESM (import/export)

Тема дорожной карты · Node.js

ECMAScript Modules (ESM) — это официальный стандарт модулей JavaScript, использующий статический синтаксис import и export, который обеспечивает возможность tree-shaking, await верхнего уровня и улучшенную поддержку инструментария в серверных проектах Node.js. Node.js поддерживает ESM нативно начиная с версии v12; пакет переходит в режим ESM, устанавливая "type": "module" в package.json или используя расширения файлов .mjs — файлы без этой настройки по умолчанию используют систему require() из CommonJS. Операторы import ESM разрешаются статически на этапе парсинга (в отличие от динамического вызова require()), что позволяет Node.js и бандлерам анализировать весь граф зависимостей и устранять неиспользуемый код. Одно из важных отличий от CommonJS состоит в том, что ESM не поддерживает синхронный require(), однако Node.js 22 позволяет импортировать CommonJS-модули с помощью import, что обеспечивает постепенную миграцию существующих серверных кодовых баз. Настройки "module" и "moduleResolution" в tsconfig.json должны соответствовать выбранной системе модулей при использовании TypeScript с Node.js, чтобы избежать ошибок разрешения во время выполнения.

Как это работает

ESM (import/export) имеет два формата: CommonJS (legacy дефолт, require/module.exports, синхронный) и ES Modules (import/export, асинхронный, browser-compatible). Файлы резолвятся загрузчиком модулей: относительные пути → обход node_modules → встроенные. "type": "module" в package.json переключает дефолт для .js; расширения .mjs и .cjs форсируют формат. Conditional exports (exports в package.json) позволяют пакету поставлять оба формата.

Когда применять

Для новых проектов ESM — это стандарт JS, поддерживает top-level await, ожидается бандлерами/тулингом. CommonJS — только когда legacy-зависимости требуют или цена миграции запретительная. import("./mod.js") — для динамической / условной загрузки. Бандлер (esbuild, tsup) — только если публикуете пакет в обоих форматах; backend-сервисы обычно гоняют исходник.

Типичные ошибки

Ловушки ESM (import/export): пропущенное расширение .js в ESM-импортах (тихо ломается); циклические импорты (A → B → A — одна сторона получает partial export); случайный бандл CommonJS-only пакета в ESM-проект (interop болезненный); __dirname/__filename отсутствуют в ESM (используйте import.meta.url). Прочтите доку Node.js ESM перед битвой с "unexpected token".

Связанные понятия

Полезные ресурсы