<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Cannot use import statement outside a module: причины и решения в JS&#x2F;Node]]></title><description><![CDATA[<p dir="auto">Ошибка <strong>Cannot use import statement outside a module</strong> часто встречается в JavaScript и Node.js. Она возникает, когда код пытается использовать современный синтаксис <code>import</code>, но среда выполнения его не понимает. Это мешает запускать модули и ломает проекты.</p>
<p dir="auto">В этой статье разберём, почему появляется ошибка, в каких сценариях она возникает и как её быстро исправить. Вы узнаете про настройки Node.js, TypeScript и браузера. После прочтения сможете настроить импорт без проблем и избежать типичных ловушек.</p>
<h2>Почему возникает ошибка в Node.js</h2>
<p dir="auto">Node.js по умолчанию работает с <strong>CommonJS</strong> модулями, где вместо <code>import</code> используется <code>require()</code>. Когда вы пишете <code>import something from 'module'</code>, движок ожидает ES-модули, но не находит их. Это приводит к <strong>SyntaxError</strong>.</p>
<p dir="auto">Представьте: вы обновили код до ES6, добавили <code>import</code>, но при запуске <code>node app.js</code> всё падает. Проблема в том, что без специальной настройки Node.js трактует <code>.js</code> файлы как CommonJS. Аналогично в проектах с bundler’ами вроде Webpack или Jest, если конфиг не поддерживает ESM.</p>
<p dir="auto">Решение подводит к изменению конфигурации. Вот ключевые шаги.</p>
<ul>
<li><strong>Добавьте в package.json</strong>: <code>"type": "module"</code>. Это скажет Node.js трактовать все <code>.js</code> как ES-модули.</li>
<li><strong>Используйте расширение .mjs</strong>: Переименуйте файл в <code>app.mjs</code> — Node.js сразу поймёт.</li>
<li><strong>Флаг для старых версий</strong>: <code>node --experimental-modules app.js</code> (до Node 13.2.0).</li>
</ul>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Ситуация</th>
<th>Решение</th>
<th>Плюсы</th>
<th>Минусы</th>
</tr>
</thead>
<tbody>
<tr>
<td>Новый проект</td>
<td><code>type: module</code> в package.json</td>
<td>Просто, работает везде</td>
<td>Весь проект на ESM</td>
</tr>
<tr>
<td>Один файл</td>
<td>.mjs расширение</td>
<td>Локально, без изменений</td>
<td>Меняете имена файлов</td>
</tr>
<tr>
<td>Старый Node</td>
<td><code>--experimental-modules</code></td>
<td>Быстро</td>
<td>Не для продакшена</td>
</tr>
</tbody>
</table>
<p dir="auto"><em>Важно</em>: После <code>type: module</code> <code>require()</code> перестанет работать — перепишите на <code>import</code>.</p>
<h2>Настройки для TypeScript проектов</h2>
<p dir="auto">В TypeScript ошибка часто из-за несоответствия между <code>module</code> в tsconfig.json и runtime. Если вы используете ESM-синтаксис, но компилятор генерит CommonJS, импорт сломается.</p>
<p dir="auto">Например, в проекте с Jest и node-fetch: <code>import fetch from 'node-fetch'</code> выдаст ошибку, потому что Jest по умолчанию на CommonJS. Или tsconfig с <code>"module": "commonjs"</code>, но код пишет <code>import</code>. Это типичная засада при миграции.</p>
<p dir="auto">Переходим к настройкам, которые исправят всё.</p>
<ol>
<li>В <strong>tsconfig.json</strong> укажите <code>"module": "esnext"</code> или <code>"es2022"</code>, а <code>target</code> — <code>es2021</code>+.</li>
<li>В <strong>package.json</strong> добавьте <code>"type": "module"</code>.</li>
<li>Для тестов в Jest: настройте <code>transform</code> или используйте Node 18+ с нативным fetch.</li>
</ol>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Конфиг</th>
<th>Для ESM</th>
<th>Для CommonJS</th>
</tr>
</thead>
<tbody>
<tr>
<td>tsconfig module</td>
<td>esnext</td>
<td>commonjs</td>
</tr>
<tr>
<td>package.json type</td>
<td>module</td>
<td>(отсутствует)</td>
</tr>
<tr>
<td>Jest</td>
<td>moduleFileExtensions: [‘js’, ‘mjs’]</td>
<td>По умолчанию</td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>Про tip</strong>: Обновите Node до 18+ — там fetch встроенный, без лишних пакетов.</p>
<h2>Исправление в браузере и bundler’ах</h2>
<p dir="auto">В браузере <code>import</code> работает только в модулях. Если скрипт без <code>type="module"</code>, ошибка неизбежна. Аналогично в Hugo, Webpack или Parcel — конфиг должен поддерживать ESM.</p>
<p dir="auto">Возьмём HTML: <code>&lt;script src="app.js"&gt;&lt;/script&gt;</code> с <code>import</code> внутри — браузер ругается. Или в старом проекте с Rollup, где target не обновлён. Такие случаи часты при деплое на старые хостинги.</p>
<p dir="auto">Простые фиксы в списке.</p>
<ul>
<li><strong>В HTML</strong>: <code>&lt;script type="module" src="app.js"&gt;&lt;/script&gt;</code>.</li>
<li><strong>Webpack</strong>: В <code>webpack.config.js</code> установите <code>experiments: { outputModule: true }</code>.</li>
<li><strong>Parcel/Rollup</strong>: Укажите <code>format: 'esm'</code> в конфиге.</li>
<li><em>Для старых браузеров</em>: Используйте bundler, чтобы скомпилировать в IIFE или UMD.</li>
</ul>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Bundler</th>
<th>Настройка ESM</th>
<th>Совместимость</th>
</tr>
</thead>
<tbody>
<tr>
<td>Webpack 5</td>
<td>experiments.outputModule</td>
<td>IE11+ с полифиллами</td>
</tr>
<tr>
<td>Rollup</td>
<td>format: ‘esm’</td>
<td>Отличная</td>
</tr>
<tr>
<td>Parcel</td>
<td>Авто</td>
<td>Все браузеры</td>
</tr>
</tbody>
</table>
<p dir="auto"><em>Нюанс</em>: В миксе CommonJS и ESM используйте динамический <code>import()</code>.</p>
<h2>Ключевые ловушки и когда переключаться на ESM</h2>
<p dir="auto">Даже после фиксов могут остаться подводные камни. Старые версии Node слабо поддерживают ESM, библиотеки вроде node-fetch 3+ требуют <code>type: module</code>. Плюс смешанные проекты: часть на <code>require</code>, часть на <code>import</code>.</p>
<p dir="auto">Это подводит к выбору стратегии. Полный переход на ESM упрощает код, но требует рефакторинга. Или останетесь на CommonJS для legacy. В 2026 году ESM — стандарт, но знайте альтернативы.</p>
<ul>
<li><strong>Проверьте версии</strong>: Node 14+ для стабильного ESM.</li>
<li><strong>Динамический импорт</strong>: <code>const mod = await import('./file.js')</code> работает везде.</li>
<li><strong>Babel</strong>: Транспайлер для смешанных сред.</li>
</ul>
<h2>Что меняется с ESM в долгосрочке</h2>
<p dir="auto">Ошибка <strong>Cannot use import statement outside a module</strong> — сигнал, что пора обновлять стек. ESM приносит tree-shaking, топ-левел await и лучшую производительность. Но legacy-код на CommonJS никуда не денется.</p>
<p dir="auto">В будущем Node продолжит улучшать поддержку, но смешанные модули потребуют hybrid-подходов. Стоит поэкспериментировать с Deno или Bun — там ESM из коробки без хлопот.</p>
]]></description><link>https://forum.exlends.ru/topic/722/cannot-use-import-statement-outside-a-module-prichiny-i-resheniya-v-js-node</link><generator>RSS for Node</generator><lastBuildDate>Sat, 17 Oct 2026 03:25:45 GMT</lastBuildDate><atom:link href="https://forum.exlends.ru/topic/722.rss" rel="self" type="application/rss+xml"/><pubDate>Tue, 24 Feb 2026 09:57:15 GMT</pubDate><ttl>60</ttl></channel></rss>