#Что означает ошибка
Cannot use import statement outside a module
SyntaxError: Cannot use import statement outside a module и ERR_REQUIRE_ESM возникают, когда Node.js запускает файл с import/export как CommonJS (или наоборот). Это несоответствие систем модулей.
Решение зависит от того, что вам удобнее: перейти на ESM или оставить CommonJS.
Ошибка возникает при использовании import в CommonJS-файле. Укажите "type": "module" в package.json или переименуйте файл в .mjs.
#Причины и решения
| Возможная причина | Как узнать | Что делать |
|---|---|---|
| CommonJS по умолчаниюТип. | Ошибка. | type module. |
| Расширение .jsCJS. | Ошибка. | .mjs. |
| Смешение require/importСтили. | Ошибка. | Унифицируйте. |
| Версия NodeСтарая. | Ошибка. | Обновите. |
#Пошаговое решение
- Определите тип модулейОткройте каталог проекта в VS Code либо другом редакторе и найдите входной файл из текста ошибки (
app.js,index.jsи т. п.). Затем откройте ближайший к немуpackage.jsonи проверьте полеtype. Расширение.mjsвсегда указывает на ES-модуль,.cjs— на CommonJS; файл.jsзависит отtypeи в современных версиях Node возможен дополнительный анализ синтаксиса. Запуститеnode -vв терминале проекта: поведение и совместимость библиотек зависят от версии. Не изменяйтеtypeвсего проекта без оценки остальных файлов. - Добавьте type moduleЕсли проект целиком рассчитан на ES-модули, добавьте в корневой для этих файлов
package.jsonполе"type": "module"или переименуйте один отдельный файл в.mjs. Перед изменением сохраните копиюpackage.jsonи проверьте скрипты запуска, тесты и конфигурационные файлы. Успешное переключение означает, что Node разбираетimport/export; однакоrequire,module.exportsи__dirnameв этом контексте больше не будут доступны — исправляйте их по необходимости. Для проектов с множеством CommonJS-зависимостей удобнее ограничиться.mjs. - Уберите require и __dirnameЕсли остаётесь в CommonJS, используйте синтаксис
const fs = require("node:fs")иmodule.exports = ...только в своих совместимых файлах; не делайте массовую автоматическую заменуimportнаrequire. Пакеты только для ESM могут не загружаться черезrequireв конкретной версии Node; для них используйте поддерживаемый динамическийimport()или мигрируйте соответствующий модуль. Проверка: запустите свою точку входаnode app.cjs(замените имя на реальное) и посмотрите, исчезла ли именно исходная ошибка. - Добавьте расширения в импортыДля нативного ESM при относительном импорте укажите явный путь с расширением:
import { foo } from "./foo.js", а для index —./dir/index.js. Проверьте, что файл действительно существует в скомпилированном результате, а регистр совпадает (Linux чувствителен к регистру). В ESM нельзя просто вызватьrequire()или использовать__dirname; если нужен каталог текущего модуля, применитеfileURLToPath(new URL(".", import.meta.url))изnode:url. Эти изменения относятся к настоящему ESM, не ко всем приложениям Node.js. - Проверьте tsconfigДля TypeScript сначала проверьте
tsconfig.json, наличие сборки и настройки проекта;"module": "NodeNext"вместе с"moduleResolution": "NodeNext"— вариант, но он должен соответствоватьpackage.jsonи фактическому способу запуска. Если ошибка происходит в Jest, ts-node или сборщике, ищите именно конфигурацию их загрузчика: изменениеtypeсамо по себе может сломать тесты. Выполните тестовый запуск исходной команды и сравните с предыдущим стеком; при новой ошибке откатите последнее изменение и согласуйте один способ модулей для проекта.
#Перейти на ESM
В package.json добавьте "type": "module" либо переименуйте файл в .mjs. Тогда import fs from "fs" работает, а require и __dirname недоступны: используйте import { fileURLToPath } from "url"; const __dirname = path.dirname(fileURLToPath(import.meta.url));. В импортах локальных файлов указывайте расширение: ./utils.js.
#Оставить CommonJS
Замените import x from "y" на const x = require("y"), а export default на module.exports =. Если пакет — ESM-only (node-fetch 3, chalk 5), установите прежнюю версию npm i node-fetch@2 либо подключайте динамически: const fetch = (...a) => import("node-fetch").then(m => m.default(...a));.
#Инструменты
В TypeScript выставьте "module": "NodeNext" или "commonjs" в tsconfig.json; для Jest настройте трансформацию и поддержку ESM по документации используемой версии. Запуск ts-node для ESM: node --loader ts-node/esm. Проверьте версию Node (node -v): стабильная поддержка ESM с 14, Поддержка require() для ESM зависит от конкретного выпуска Node и ограничений модуля; не считайте её универсальной.
#Как проверить результат
Создайте файл test.mjs с содержимым import os from "os"; console.log(os.platform()); и запустите node test.mjs: если вывод появился, ESM работает. Для CommonJS проверьте node -e "console.log(require('os').platform())". Если ошибка осталась в Jest, проверьте jest.config.js и параметры transformIgnorePatterns для ESM-пакетов из node_modules.