Перейти к содержимому

Домены и субдомены

Фрактальность обещает: структура повторяется на всех уровнях. Этот раздел показывает, как это устроено на практике — как выглядит домен, когда из него стоит выносить субдомен и как модули общаются друг с другом, не ломая границы.

Структура домена

Домен — это модуль верхнего уровня внутри routes/. Он отвечает признакам:

  • Задаётся бизнесом, а не техникой. Домен «корзина» существует потому, что корзина есть в требованиях, — а не потому, что так удобно разложить компоненты.
  • Понятен всем участникам. Разработчик, менеджер и заказчик одинаково понимают, что лежит в cart/ — им не нужно знать архитектуру, только бизнес.
  • Владеет своим кодом целиком. От разметки страницы до запросов к базе: изменения фичи не выходят за пределы одной папки.
  • Определяет структуру приложения. Список папок в routes/ — это карта продукта. Новый раздел требований — новый домен.

Граница домена проходит по границе фичи. Если изменение требования «доставка считается от содержимого корзины» затрагивает два домена — это нормально: вы меняете контракт между ними, а не смешиваете их код. Как именно — в разделе о кросс-доменном взаимодействии.

Когда домен растёт, его части выносятся в субдомены. У субдомена два вида:

ВидПапкаРоутингКогда использовать
Публичныйcart/items/есть: /cart/itemsЧасть домена со своей страницей или API
Приватныйcart/_checkout/нет: _ прячет от роутераДекомпозиция больших кусков логики без собственного URL

У субдомена — та же структура, что и у домена: своя модель, свой контроллер, свои типы. Фрактальность в действии: открыв cart/items/, вы видите то же устройство, что и в cart/, только масштаб меньше.

src/routes/
└── cart/ # домен «корзина»
├── +page.svelte # страница корзины
├── +page.server.ts # server load
├── +server.ts # HTTP-роут: действия
├── rpc.ts # API для других доменов
├── client.ts # браузерные вызовы
├── model.server.ts # операции с данными
├── controller.svelte.ts # реактивное состояние
├── schema.ts # таблицы ORM
├── types.ts # типы домена
├── templates.ts # шаблоны форм
├── constants.ts # константы, enum
├── policy.ts # правила доступа
├── utils.ts # хелперы модуля
├── index.ts # публичный API
├── ui/ # внутренние компоненты
│ ├── CartWidget.svelte
│ ├── CartItemCard.svelte
│ └── CheckoutForm.svelte
│
├── _checkout/ # приватный субдомен: без URL
│ ├── rpc.ts
│ ├── model.server.ts
│ ├── controller.svelte.ts
│ ├── types.ts
│ ├── constants.ts
│ ├── policy.ts
│ ├── index.ts
│ └── ui/
│ └── PaymentStep.svelte
│
└── items/ # публичный субдомен: /cart/items
├── +page.svelte
├── +page.server.ts
├── rpc.ts
├── model.server.ts
├── controller.svelte.ts
├── types.ts
├── constants.ts
├── policy.ts
├── index.ts
└── ui/
└── ItemList.svelte

Комментарии в дереве — роли файлов в одну строку; подробные контракты и наборы экспортов — в разделе 05.

Имена файлов приведены для SvelteKit — в Next.js и Nuxt они называются по конвенции фреймворка (таблица соответствия — в основных концепциях); роли от фреймворка не зависят.

Границы доменов существуют, чтобы изменения в одном месте не ломали другое. Но модули не изолированы: корзина отдаёт число товаров в шапку, чекаут читает содержимое корзины. У связей два вида — родитель с потомком и соседние домены первого уровня, — и правила у них разные: потомку доступно больше, соседу только публичный вход. Оба случая с примерами — в разделе 06.

Порядок шагов повторяет движение данных снизу вверх: от источника данных к разметке.

  1. Создайте папку в routes/

    Имя — из требований бизнеса: cart, auth, orders. Путь и имена файлов роутинга зависят от фреймворка: src/routes/cart/ в SvelteKit, app/cart/ в Next.js, pages/cart/ в Nuxt.

  2. Соберите файлы по контрактам

    Минимальный набор: страница, её серверная часть, rpc.ts, model.server.ts, контроллер и index.ts; остальное добавляется по задаче. Роль и экспорты каждого файла — в разделе 05.

  3. Опубликуйте вход и проверьте импорты

    +server.ts и client.ts — для браузера, rpc.ts — для соседних доменов; каждый обработчик валидирует вход и вызывает одну функцию модели. Импорты — только вниз по слоям. Прогоните результат по чеклисту из раздела 07.

Тот же порядок использует AI-агент со скиллом FDA — он собирает домен по этим шагам и сам проверяет направление зависимостей.

→ Контракты файлов — роль и экспорты каждого файла из дерева выше

→ Кросс-доменное взаимодействие — родитель и потомок, соседние домены, алиасы

→ FAQ и чеклист — ручная проверка модуля перед мержем