Cannot use import statement outside a module: причины и решения в JS/Node
-
Ошибка Cannot use import statement outside a module часто встречается в JavaScript и Node.js. Она возникает, когда код пытается использовать современный синтаксис
import, но среда выполнения его не понимает. Это мешает запускать модули и ломает проекты.В этой статье разберём, почему появляется ошибка, в каких сценариях она возникает и как её быстро исправить. Вы узнаете про настройки Node.js, TypeScript и браузера. После прочтения сможете настроить импорт без проблем и избежать типичных ловушек.
Почему возникает ошибка в Node.js
Node.js по умолчанию работает с CommonJS модулями, где вместо
importиспользуетсяrequire(). Когда вы пишетеimport something from 'module', движок ожидает ES-модули, но не находит их. Это приводит к SyntaxError.Представьте: вы обновили код до ES6, добавили
import, но при запускеnode app.jsвсё падает. Проблема в том, что без специальной настройки Node.js трактует.jsфайлы как CommonJS. Аналогично в проектах с bundler’ами вроде Webpack или Jest, если конфиг не поддерживает ESM.Решение подводит к изменению конфигурации. Вот ключевые шаги.
- Добавьте в package.json:
"type": "module". Это скажет Node.js трактовать все.jsкак ES-модули. - Используйте расширение .mjs: Переименуйте файл в
app.mjs— Node.js сразу поймёт. - Флаг для старых версий:
node --experimental-modules app.js(до Node 13.2.0).
Ситуация Решение Плюсы Минусы Новый проект type: moduleв package.jsonПросто, работает везде Весь проект на ESM Один файл .mjs расширение Локально, без изменений Меняете имена файлов Старый Node --experimental-modulesБыстро Не для продакшена Важно: После
type: modulerequire()перестанет работать — перепишите наimport.Настройки для TypeScript проектов
В TypeScript ошибка часто из-за несоответствия между
moduleв tsconfig.json и runtime. Если вы используете ESM-синтаксис, но компилятор генерит CommonJS, импорт сломается.Например, в проекте с Jest и node-fetch:
import fetch from 'node-fetch'выдаст ошибку, потому что Jest по умолчанию на CommonJS. Или tsconfig с"module": "commonjs", но код пишетimport. Это типичная засада при миграции.Переходим к настройкам, которые исправят всё.
- В tsconfig.json укажите
"module": "esnext"или"es2022", аtarget—es2021+. - В package.json добавьте
"type": "module". - Для тестов в Jest: настройте
transformили используйте Node 18+ с нативным fetch.
Конфиг Для ESM Для CommonJS tsconfig module esnext commonjs package.json type module (отсутствует) Jest moduleFileExtensions: [‘js’, ‘mjs’] По умолчанию Про tip: Обновите Node до 18+ — там fetch встроенный, без лишних пакетов.
Исправление в браузере и bundler’ах
В браузере
importработает только в модулях. Если скрипт безtype="module", ошибка неизбежна. Аналогично в Hugo, Webpack или Parcel — конфиг должен поддерживать ESM.Возьмём HTML:
<script src="app.js"></script>сimportвнутри — браузер ругается. Или в старом проекте с Rollup, где target не обновлён. Такие случаи часты при деплое на старые хостинги.Простые фиксы в списке.
- В HTML:
<script type="module" src="app.js"></script>. - Webpack: В
webpack.config.jsустановитеexperiments: { outputModule: true }. - Parcel/Rollup: Укажите
format: 'esm'в конфиге. - Для старых браузеров: Используйте bundler, чтобы скомпилировать в IIFE или UMD.
Bundler Настройка ESM Совместимость Webpack 5 experiments.outputModule IE11+ с полифиллами Rollup format: ‘esm’ Отличная Parcel Авто Все браузеры Нюанс: В миксе CommonJS и ESM используйте динамический
import().Ключевые ловушки и когда переключаться на ESM
Даже после фиксов могут остаться подводные камни. Старые версии Node слабо поддерживают ESM, библиотеки вроде node-fetch 3+ требуют
type: module. Плюс смешанные проекты: часть наrequire, часть наimport.Это подводит к выбору стратегии. Полный переход на ESM упрощает код, но требует рефакторинга. Или останетесь на CommonJS для legacy. В 2026 году ESM — стандарт, но знайте альтернативы.
- Проверьте версии: Node 14+ для стабильного ESM.
- Динамический импорт:
const mod = await import('./file.js')работает везде. - Babel: Транспайлер для смешанных сред.
Что меняется с ESM в долгосрочке
Ошибка Cannot use import statement outside a module — сигнал, что пора обновлять стек. ESM приносит tree-shaking, топ-левел await и лучшую производительность. Но legacy-код на CommonJS никуда не денется.
В будущем Node продолжит улучшать поддержку, но смешанные модули потребуют hybrid-подходов. Стоит поэкспериментировать с Deno или Bun — там ESM из коробки без хлопот.
- Добавьте в package.json:
© 2024 - 2025 ExLends, Inc. Все права защищены.