Node.js: Cannot use import statement outside a module — как исправить ошибку
-
В Node.js часто возникает ошибка Cannot use import statement outside a module. Она появляется, когда вы пытаетесь использовать современный синтаксис
importв проекте, который по умолчанию работает на CommonJS. Эта проблема тормозит разработку, но её легко ��справить несколькими способами.Понимание причины поможет избежать повторений. Мы разберём, почему Node.js не понимает
import, и покажем проверенные решения. Вы узнаете, как настроить проект под ES6-модули, перейти на CommonJS или использовать флаги. После этого код заработает без лишних хлопот.Почему возникает ошибка и что такое модули в Node.js
Node.js по умолчанию использует систему CommonJS с
require()иmodule.exports. Это старый стандарт, который не понимаетimport/exportиз ES6. Когда вы пишетеimport { func } from './module.js', движок думает, что файл — это обычный скрипт, а не модуль.Проблема типична для новых проектов на ES6-модулях, где хочется tree-shaking и статического анализа. Представьте: вы копируете код из браузерного примера в серверный скрипт — и бац, ошибка. Node.js с версии 12+ поддерживает ES6, но требует явной активации. Без неё парсер ругается на неподдерживаемый синтаксис.
Это подводит к первым шагам исправления. Давайте разберём варианты по шагам.
- Проверьте версию Node.js: Запустите
node -v. ES6-модули стабильно работают с v14+. Если версия старая, обновите. - Анализ package.json: Отсутствие поля
"type": "module"— частая причина. Node.js интерпретирует.jsкак CommonJS. - Расширение файлов:
.jsпо умолчанию — CommonJS,.mjs— ES-модуль. Простая переименование решает 30% случаев.
Система модулей Синтаксис импорта Требования Node.js CommonJS require()По умолчанию ES6 import"type": "module"или.mjsВажно: В ES6 всегда указывайте расширения в путях, типа
./module.js, иначе ошибка persists.Решение 1: Активация ES6-модулей через package.json
Самый удобный способ для ц��лого проекта — добавить настройку в package.json. Это говорит Node.js: “Все
.js-файлы здесь — ES-модули”. Откройте файл и вставьте строку"type": "module".После этого
importзаработает везде. Но учтите: весь проект перейдёт на ES6, так чтоrequire()сломается. Если в коде есть legacy-библиотеки, это вызовет новые проблемы. Пример: простой сервер на Express с импортами.// package.json { "type": "module", "dependencies": { "express": "^4.18.0" } } // app.js import express from 'express'; const app = express(); app.get('/', (req, res) => res.send('Hello!')); app.listen(3000);Запуск:
node app.js— и вуаля, без ошибок. Это решение масштабируется для больших приложений.- Создайте или отредактируйте
package.json. - Добавьте
"type": "module"на верхний уровень. - Укажите расширения в импортах:
import './file.js'. - Перезапустите скрипт.
Плюсы Минусы Просто для всего проекта Требует рефакторинга CommonJS Поддержка tree-shaking Не для микс-проектов Нюанс: Если проект на TypeScript, настройте
tsconfig.jsonс"module": "ESNext".Решение 2: Переход на CommonJS или использование .mjs
Если не хотите менять весь проект, вернитесь к CommonJS. Замените
importнаrequire(),exportнаmodule.exports. Это быстро, но теряет преимущества ES6, вроде статических импортов.Пример трансформации:
// Было (ES6) export const sum = (a, b) => a + b; // Стало (CommonJS) const sum = (a, b) => a + b; module.exports = { sum }; // Импорт // Было: import { sum } from './utils.js'; // Стало: const { sum } = require('./utils');Альтернатива — переименуйте файл в
app.mjs. Node.js сразу поймёт это как ES-модуль, без package.json. Идеально для тестов или скриптов.- Для отдельных файлов:
mv app.js app.mjs, затемnode app.mjs. - Destructuring работает:
const { func } = require('./mod'). - Бандлеры спасут: Webpack или Babel транслируют ES6 в CommonJS автоматически.
Метод Когда использовать CommonJS Legacy-код, простые скрипты .mjs Быстрые тесты, прототипы Babel Совместимость с IE/старым Node Совет: В продакшене комбинируйте с bundler’ами для оптимизации.
Дополнительные инструменты и подводные камни
Иногда базовые способы не помогают — из-за bundler’ов или браузера. В браузере добавьте
type="module"в<script>. Node.js флаг--experimental-modulesустарел, используйте современные версии.Проверьте пути: относительные
./обязательны в ES6. Абсолютные или без расширений — ошибка. Для TypeScript компилируйте сtsc --module esnext.<!-- Браузер --> <script type="module" src="app.js"></script>- Webpack/Vite: Настройте
output.library.type: 'module'. - Babel:
.babelrcс@babel/preset-env. - Dynamic import:
const mod = await import('./file.js')— асинхронно. - npm/yarn:
npxдля разовых скриптов.
Инструмент Преимущества Vite Быстрая HMR, ES6 из коробки Webpack Бандлинг + polyfill’y esbuild Суперскорость Предупреждение: Микс CommonJS/ES6 в одном проекте — источник багов.
Когда выбрать каждый подход под вашу задачу
Ошибку можно исправить по-разному, в зависимости от проекта. Для серверов на чистом Node.js берите
package.jsonсtype: module. Маленькие скрипты —.mjsили CommonJS. Большие apps требуют bundler’ов вроде Vite.Оставшиеся нюансы: динамические импорты, CJS-библиотеки в ESM (используйте
createRequire). Подумайте о миграции на ESM полностью — будущее за ним. В новых версиях Node.js CommonJS потихоньку уходит.Это базовые инструменты для стабильного кода. Дальше экспериментируйте с top-level await в ESM — там ещё фишки ждут.
- Проверьте версию Node.js: Запустите
Здравствуйте! Похоже, вас заинтересовала эта беседа, но у вас ещё нет аккаунта.
Надоело каждый раз пролистывать одни и те же посты? Зарегистрировав аккаунт, вы всегда будете возвращаться на ту же страницу, где были раньше, и сможете выбирать, получать ли уведомления о новых ответах (по электронной почте или в виде push-уведомлений). Вы также сможете сохранять закладки и ставить лайки постам, чтобы выразить свою благодарность другим участникам сообщества.
С вашими комментариями этот пост мог бы стать ещё лучше 💗
Зарегистрироваться Войти© 2024 - 2026 ExLends, Inc. Все права защищены.