Реэкспорт и структура проекта

Реэкспорт и структура проекта

Технический фундамент реэкспорта

Реэкспорт это слой абстракции между внутренней структурой папок и внешними потребителями:

  • внешние модули зависят от стабильной точки входа (index.js);
  • внутренние файлы можно перемещать без массовой правки импортов;
  • публичный API становится явным и управляемым;
  • снижается связность между слоями проекта.

Техническая цель: минимизировать число "глубоких импортов" и держать зависимости на уровне контрактов, а не путей.

Почему реэкспорт нужен в реальном проекте

Когда проект растет, количество модулей увеличивается, и импорты начинают "расползаться" по множеству путей. Реэкспорт помогает собрать публичное API слоя или папки в одном месте. Это упрощает подключение модулей и делает структуру проекта понятнее.

Ключевой момент: реэкспорт это экспорт того, что уже экспортировано в другом модуле.

Проверь себя: чем удобен один входной файл API папки вместо десятка точечных импортов из глубины структуры?

Базовый синтаксис реэкспорта

Самая частая форма:

// utils/index.js
export { formatPrice } from './formatPrice.js';
export { formatDate } from './formatDate.js';

Теперь в потребителе:

import { formatPrice, formatDate } from './utils/index.js';

Смотри, что важно: модуль index.js становится "витриной" папки utils.

Реэкспорт всего модуля

Иногда используют export * from ....

export * from './validators.js';
export * from './sanitizers.js';

Это быстро, но есть риск конфликтов имен, если в разных модулях есть одинаковые экспорты.

Анти-провал: если API публичный и долгоживущий, лучше явный реэкспорт с конкретными именами.

Реэкспорт default-экспорта

Default можно реэкспортировать под именем.

// api/index.js
export { default as userApi } from './userApi.js';
export { default as orderApi } from './orderApi.js';

Так ты получаешь единый импорт:

import { userApi, orderApi } from './api/index.js';

Здесь часто путаются: default не переносится автоматически через export *. Для него обычно нужен явный синтаксис.

Проверь себя: почему export * from './userApi.js' может не дать ожидаемый доступ к default?

Как реэкспорт связан со структурой проекта

Хорошая структура обычно имеет уровни:

  • features/... или modules/... - бизнес-фичи;
  • shared/... - общие утилиты/компоненты;
  • api/... - сетевой слой;
  • index.js в ключевых папках как публичная точка входа.

Мини-термин: public API модуля - набор экспортов, который команда считает стабильным и поддерживаемым.

Это дисциплинирует архитектуру: внутренние файлы можно менять, пока внешний контракт (index.js) сохраняется.

Микро-сценарии из продукта

  1. Большая форма checkout.

Есть папка checkout/ с валидацией, расчетами, API и UI-хелперами. Через checkout/index.js наружу экспортируются только необходимые функции и компоненты.

  1. Переход на новую реализацию API.

Ты меняешь внутренний userApi.js, но внешний импорт import { userApi } from './api' у остальных модулей остается прежним.

Это снижает стоимость рефакторинга.

Типичные ошибки новичков

  • Делать реэкспорт всего подряд без контроля публичного API.
  • Создавать "циклические" зависимости через неаккуратные index.js.
  • Путать внутренние файлы и публичные точки входа.
  • Держать неочевидные и слишком длинные цепочки реэкспорта.
// Плохо: слишком расплывчатый API
export * from './everything.js';

Лучше явно перечислить, что должно использоваться другими частями системы.

Что будет, если изменить структуру папок

Если у тебя есть стабильный index.js как публичный вход, внутренний перенос файлов может не затронуть потребителей. Если же все импортируют глубокие пути напрямую, любое перемещение файлов вызовет массовые правки.

Проверь себя: какой подход уменьшит количество изменений при рефакторинге - глубокие прямые импорты или публичные index.js?

Практичный мини-чеклист

  1. Есть ли у каждой крупной папки понятный публичный вход (index.js)?
  2. Экспортируются ли только действительно нужные сущности?
  3. Нет ли конфликтов имен и циклических зависимостей?
  4. Понятно ли новому разработчику, откуда правильно импортировать модуль?

Дополнительный пример: ограниченный публичный API через index.js.

// cart/index.js
export { addItem, removeItem } from './cartActions.js';
// Внутренние детали cartState.js наружу не экспортируем

// checkoutPage.js
import { addItem } from './cart/index.js';

Так команда явно контролирует, какие части модуля считаются публичными, а какие остаются внутренней реализацией.

Краткий итог

  • Реэкспорт помогает собрать единый публичный API модулей и папок.
  • index.js часто используется как точка входа для удобных импортов.
  • Явный реэкспорт обычно безопаснее, чем безконтрольный export *.
  • Продуманная структура проекта снижает связность и упрощает рефакторинг.
  • Цель реэкспорта - не "красивые импорты", а управляемая и стабильная архитектура.