Learn JavaScript

import/export: модули

Модули помогают разделять код на файлы, чтобы:

  • не держать все в одном скрипте
  • переиспользовать функции и данные
  • сделать проект понятнее: что где лежит и за что отвечает

В браузере и во многих сборщиках (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 - загрузка JSON
  • storage/cache.js - мини-кеш
  • ui/render.js - отрисовка

Что стоит запомнить

  • export отдает наружу функции и данные из файла, import подключает их в другом файле.
  • Именованный export - импорт в фигурных скобках, default - без скобок.
  • Для браузера нужен type="module" и корректные пути к файлам.
  • Большинство проблем с модулями - это не синтаксис, а пути и смешивание default/named.