Запрос «как сделать es» чаще всего означает одно из двух: создать ES-модуль в JavaScript (файл с export/import) или подключить скрипт как модуль через type="module". Если скрипт с import выдаёт в консоли ошибку «Cannot use import statement outside a module» — это верный признак, что файл загружается как обычный скрипт, а не как ES-модуль.
Ниже разберём оба сценария: создание модуля с экспортом функций, подключение его в браузере и в Node.js, а также типичные ошибки. Если под «es» вы имели в виду что-то другое (например, файл конфигурации или испанскую раскладку), уточните задачу — общие принципы работы с файлами из статьи всё равно пригодятся.
Что такое ES-модуль и чем он отличается от обычного скрипта
ES-модуль — это файл JavaScript, который использует стандартные ключевые слова export и import, появившиеся в спецификации ECMAScript 2015 (ES6). В отличие от классического скрипта, модуль имеет собственную область видимости: переменные, объявленные внутри него, не попадают в глобальный объект window.
Ещё одно отличие — модули по умолчанию работают в строгом режиме (strict mode), а их загрузка в браузере происходит отложенно, как у скрипта с атрибутом defer. Это влияет на порядок выполнения кода и на то, какие ошибки вы увидите при нарушении правил.
ES-модуль — это обычный JS-файл с export/import, который браузер или Node.js загружает в особом режиме с изолированной областью видимости.
Как создать ES-модуль: экспорт функций и переменных
Создайте обычный текстовый файл с расширением .js, например utils.js. Внутри опишите функции или константы и пометьте те из них, которые должны быть доступны снаружи, ключевым словом export.
// utils.js
export const VERSION = "1.0";
export function sum(a, b) {
return a + b;
}
export default function greet(name) {
return `Привет, ${name}!`;
}
Различают два вида экспорта. Именованный экспорт (export function sum) позволяет вывозить из файла несколько сущностей, а экспорт по умолчанию (export default) — только одну на файл. Смешивать оба подхода в одном модуле можно, как показано в примере выше.
- 📦 Именованный экспорт — для наборов функций и констант
- ⭐ Экспорт по умолчанию — для главной сущности модуля
- 🔒 Всё без export остаётся приватным внутри файла
Как подключить ES-модуль в браузере
Чтобы браузер трактовал скрипт как модуль, добавьте в тег script атрибут type="module". Без него встреченный import вызовет синтаксическую ошибку.
<script type="module">
import greet from "./utils.js";
import { sum, VERSION } from "./utils.js";
console.log(greet("мир"));
console.log(sum(2, 3), VERSION);
</script>
Обратите внимание на путь ./utils.js: в браузерных модулях расширение файла указывать обязательно, а относительный путь начинается с ./ или ../. Голое имя вроде import ... from "utils" браузер без дополнительных инструментов (import map или сборщика) не разрешит.
⚠️ Внимание: ES-модули не работают при открытии HTML-файла напрямую по протоколуfile://— браузер блокирует такие запросы из соображений безопасности. Запустите локальный сервер, например через расширение редактора или командуnpx serve, и открывайте страницу по адресуhttp://localhost.
☑️ Проверка перед запуском модуля в браузере
Как сделать ES-модуль в Node.js
В Node.js исторически использовалась система CommonJS с require и module.exports. Чтобы включить поддержку ES-модулей, есть два общепринятых способа: дать файлу расширение .mjs либо добавить в package.json поле "type": "module". Во втором случае все файлы .js проекта будут считаться ES-модулями.
{
"name": "my-project",
"type": "module"
}
После этого синтаксис import/export работает так же, как в браузере. Учтите: в Node.js при импорте локальных файлов расширение тоже обязательно, а импорт JSON-файлов и встроенных модулей имеет свои особенности — детали зависят от версии Node.js, поэтому сверяйтесь с официальной документацией вашей версии.
Типичные ошибки и их причины
Большинство проблем при переходе на ES-модули сводится к нескольким повторяющимся сценариям. Таблица ниже помогает быстро сопоставить сообщение об ошибке с вероятной причиной.
| Ошибка | Вероятная причина | Что проверить |
|---|---|---|
| Cannot use import statement outside a module | Файл загружен как обычный скрипт | Атрибут type="module" или поле "type": "module" |
| Failed to fetch dynamically / CORS | Страница открыта по file:// | Запуск через локальный сервер |
| The requested module does not provide an export | Имя в import не совпадает с экспортом | Точное написание и регистр имён |
| Cannot find module | Неверный путь или нет расширения | Префикс ./ и суффикс .js |
Отдельного внимания заслуживает смешение двух систем модулей. Если в проекте с "type": "module" остался файл с require(), он перестанет работать — такие файлы нужно либо переписать на import, либо переименовать в .cjs, чтобы Node.js трактовал их как CommonJS.
⚠️ Внимание: импорт и экспорт чувствительны к регистру имён.export function sumиimport { Sum }— разные идентификаторы, и на некоторых файловых системах регистр важен даже в именах самих файлов. Проверяйте соответствие символ в символ.
Если проект большой и использует сторонние пакеты, рассмотрите сборщик вроде Vite — он сам разрешает пути, собирает модули в бандл и избавляет от рутины с расширениями файлов.
Именованный импорт против импорта по умолчанию
Частый вопрос новичков: почему один импорт пишется в фигурных скобках, а другой — без них. Правило простое. Именованные экспорты импортируются строго по имени в скобках: import { sum } from "./utils.js". Экспорт по умолчанию импортируется без скобок, и имя при импорте можно выбрать любое: import greet from "./utils.js".
Комбинированная форма import greet, { sum } from "./utils.js" тоже допустима. Если нужно забрать всё содержимое модуля разом, используйте конструкцию import * as utils from "./utils.js" — тогда все экспорты окажутся свойствами объекта utils.
Динамический импорт — что это
Кроме статического import существует динамический: import("./utils.js").then(m => m.sum(1, 2)). Он возвращает промис и позволяет загружать модуль по требованию — например, только когда пользователь открыл определённый раздел страницы. Это сокращает время первоначальной загрузки.
Часто задаваемые вопросы
Чем ES-модуль отличается от CommonJS?
ES-модули используют import/export и являются стандартом языка, тогда как CommonJS с require/module.exports — историческая система Node.js. ES-модули поддерживают статический анализ и динамический импорт через промисы; в браузере работает только формат ES.
Почему import работает в Node.js, но не в браузере?
Скорее всего, в браузере скрипт подключён без атрибута type="module", либо страница открыта по протоколу file://. Также браузер требует полный путь с расширением файла, а Node.js в некоторых случаях допускает сокращения.
Можно ли использовать import без сборщика в реальном проекте?
Да, современные браузеры поддерживают ES-модули нативно. Ограничения: нужен сервер вместо file://, явные расширения в путях и осторожность со сторонними библиотеками, распространяемыми не в модульном формате.
Что делать, если библиотека экспортирует только CommonJS?
В Node.js CommonJS-модули обычно можно импортировать из ES-модуля через импорт по умолчанию. В браузере потребуется сборщик (Vite, Webpack, Rollup) либо версия библиотеки, собранная специально в формате ES.
Нужно ли писать "use strict" в ES-модуле?
Нет. Код внутри ES-модуля автоматически выполняется в строгом режиме, директива избыточна.
Для браузера достаточно type="module" и локального сервера, для Node.js — поля "type": "module" в package.json. Остальное — внимательность к путям, расширениям и регистру имён.