Модули помогают разделять код на файлы, чтобы:
- не держать все в одном скрипте
- переиспользовать функции и данные
- сделать проект понятнее: что где лежит и за что отвечает
В браузере и во многих сборщиках (Vite, Astro, Webpack) используется стандарт ES Modules (ESM): export и import.
1) export и import - базовая идея
Один файл что-то экспортирует:
export function sum(a, b) {
return a + b;
}
Другой файл это импортирует:
import { sum } from "./sum.js";
console.log(sum(2, 3));
2) Модуль в браузере: type=“module”
Чтобы import работал прямо в браузере, скрипт должен быть модулем:
<script type="module" src="/main.js"></script>
Особенности type="module":
- код выполняется в строгом режиме (strict mode)
- у модуля своя область видимости (переменные не становятся глобальными)
importработает только с корректными путями- при открытии файла как
file://часто возникают ограничения, обычно нужен локальный сервер
3) Именованный export (named export)
Именованный export - когда экспортируется несколько сущностей по именам.
math.js
export function sum(a, b) {
return a + b;
}
export function diff(a, b) {
return a - b;
}
main.js
import { sum, diff } from "./math.js";
console.log(sum(10, 5));
console.log(diff(10, 5));
Переименование при импорте
import { sum as add } from "./math.js";
console.log(add(1, 2));
4) export default (экспорт по умолчанию)
export default - когда у файла один главный экспорт.
format.js
export default function formatPrice(value) {
return value.toFixed(2);
}
main.js
import formatPrice from "./format.js";
console.log(formatPrice(12.5));
Важно:
- при
defaultимпорт без фигурных скобок - имя при импорте можно выбрать любое (но лучше понятное)
5) Совмещенный вариант: default + named
Так делать можно, но использовать стоит осознанно.
api.js
export default function buildUrl(path) {
return "/api/" + path;
}
export function loadStatus() {
return "ok";
}
main.js
import buildUrl, { loadStatus } from "./api.js";
console.log(buildUrl("users"));
console.log(loadStatus());
6) Экспорт “в конце” и реэкспорт
Иногда удобно объявить, а экспортировать ниже.
function sum(a, b) {
return a + b;
}
function diff(a, b) {
return a - b;
}
export { sum, diff };
Реэкспорт из index.js
Частый паттерн - собирать экспорты модуля в одном файле.
utils/sum.js
export function sum(a, b) {
return a + b;
}
utils/index.js
export { sum } from "./sum.js";
main.js
import { sum } from "./utils/index.js";
console.log(sum(2, 2));
7) Пути: ./ и ../ и почему это важно
В import путь почти всегда явный:
./file.js- файл в текущей папке../file.js- файл на уровень выше/file.js- путь от корня сайта (в браузере)
Пример:
import { sum } from "./utils/sum.js";
import { format } from "../shared/format.js";
8) Про расширения: почему часто нужен .js
В браузере в import обычно нужен полный путь, включая расширение:
import { sum } from "./sum.js";
Если проект использует сборщик (например, Vite/Astro), он может уметь подставлять расширения, но на это лучше не рассчитывать, если цель - предсказуемый код.
9) Частые ошибки и быстрые объяснения
1) Пытаться импортировать в обычном script
<script src="/main.js"></script>
В таком скрипте import не работает. Нужно type="module".
2) Ошибка “Cannot use import statement outside a module”
Причина - файл запущен не как модуль (нет type="module", или среда не поддерживает ESM в таком виде).
3) Ошибка пути (404 на файл модуля)
Если импорт указывает на несуществующий файл, модуль не загрузится.
import { sum } from "./utils/summ.js";
В этом примере опечатка: summ.js. Браузер запросит файл и получит 404.
4) Перепутать default и named
sum.js
export default function sum(a, b) {
return a + b;
}
Если импортировать так, будет ошибка:
import { sum } from "./sum.js";
Правильно:
import sum from "./sum.js";
10) Мини-правила структуры проекта
- Один файл - одна зона ответственности (например, форматирование, работа с API, вычисления).
- Имена файлов по смыслу:
format.js,api.js,dom.js,storage.js. - Папки по смыслу:
utils/,api/,ui/илиcomponents/. - В
main.jsобычно только “склейка”: импорт функций и запуск.
Пример набора файлов:
main.js- точка входаapi/loadJson.js- загрузка JSONstorage/cache.js- мини-кешui/render.js- отрисовка
Что стоит запомнить
exportотдает наружу функции и данные из файла,importподключает их в другом файле.- Именованный export - импорт в фигурных скобках, default - без скобок.
- Для браузера нужен
type="module"и корректные пути к файлам. - Большинство проблем с модулями - это не синтаксис, а пути и смешивание default/named.