Почему нет barrel-файлов
Короткий ответ: barrel прячет граф. Развёрнуто — что ломается и какие есть альтернативы.
Короткий ответ
Barrel-файл (index.ts с export { Foo } from './foo') прячет реальные зависимости. Линтер и dma check строят граф по путям импорта — через barrel граф врёт. Поэтому DMA запрещает barrel внутри модулей и требует прямых импортов в */public/*.
Что такое barrel
// features/checkout/public/index.ts ✗
export { CheckoutPage } from "./checkout-page";
export { useCheckout } from "./use-checkout";Потребитель пишет:
import { CheckoutPage } from "@/features/checkout/public";Выглядит удобно. Но анализатор видит импорт в public/index.ts, а не в checkout-page.tsx. Реальная связь между модулями теряется.
Что ломается
1. Граф зависимостей. dma check не может точно сказать, кто от кого зависит. Циклы и promotion (feature → service) определяются по рёбрам — barrel размывает рёбра.
2. Tree-shaking и бандлер. Barrel часто тянет за собой лишний код: импортировали одну функцию — получили весь модуль.
3. Рефакторинг. Переименовали файл — сломались все импорты через barrel, хотя прямых потребителей было двое.
4. Ложное чувство API. Barrel намекает «импортируй что угодно из папки». DMA наоборот требует явный контракт: каждый точка входа — отдельный файл в плоском public/.
Что DMA разрешает вместо barrel
Прямой импорт в файл:
import { CheckoutPage } from "@/features/checkout/public/checkout-page";На стадии 0 (один файл-модуль) весь файл публичен — импортируйте checkout.tsx напрямую.
Реэкспорт 1:1 из public/ во внутренний файл допустим как symlink, но по умолчанию пишите реализацию прямо в public/.
«Но в npm-пакетах же index.ts»
Пакет на границе публикации (стадия 4) — другая история: там exports в package.json — явный контракт. Внутри приложения модуль — не пакет, и граф должен быть прозрачен для инструментов.
Альтернативы, от которых отказались
| Подход | Почему нет |
|---|---|
Barrel только в public/ | Всё равно прячет, какой точка входа кто тянет |
| «Разрешим barrel, но запретим циклы» | Циклы не видны, если граф неточный |
| Авто-генерация barrel | Ещё один слой магии, который расходится с файловой системой |
Связанные темы
- Правило в концепциях: Модули и public API
- Инвариант: Четыре инварианта — «публичный API без barrels»
- Инструменты: правило
no-barrelв dma check и ESLint