Vue + Vite
DMA на Vue 3: SFC, composables, provide/inject.
Запускаемый Vue 3 + Vite пример: корень композиции src/app/, SFC modules, размещённый рядом composables, provide/inject для сквозной контекст.
Исходники: examples/vue-vite.
Корень композиции
src/app/
├── App.vue # nav, badges, монтирование */public/*
├── AppProviders.vue # provide(shopThemeKey, …)
└── app.css # global reset + CSS variablesApp.vue склеивает catalog и notifications через emit → public API — без feature → feature:
<CatalogPage @added-to-cart="onAddedToCart" />import { addNotification } from "@/features/notifications/public/notifications-api";Composables rule
Composables остаются в feature folder, пока второй модуль не импортирует ту же логику:
| Composable | Где | Почему |
|---|---|---|
use-catalog-search.ts | features/catalog/ | Только catalog |
use-checkout.ts | features/checkout/ | Только checkout |
use-notifications.ts | features/notifications/ | Только notifications |
Promotion: product state → services/, pure helpers → shared/lib.
provide / inject
Cross-cutting theme — в app, не в feature:
<!-- AppProviders.vue -->
<script setup>
import { provide } from "vue";
import { shopThemeKey } from "@/shared/domain/shop-theme";
provide(shopThemeKey, { accent: "teal" });
</script><!-- features/profile.vue -->
<script setup>
import { inject } from "vue";
import { shopThemeKey } from "@/shared/domain/shop-theme";
const theme = inject(shopThemeKey);
</script>Injection keys в shared/domain/ — portable, без product logic.
SFC boundaries
| Файл | Слой |
|---|---|
App.vue | app/ — монтирование */public/* only |
AppProviders.vue | app/ — provide context |
catalog-page.vue | feature public/ — relative → composables |
profile.vue | стадия-0 — inject |
cart.ts | service — framework-agnostic |
public/ импортирует внутренности через относительные пути (../use-catalog.ts). Межмодульные — @/ aliases на */public/*.
Куда класть код
| Задача | Папка |
|---|---|
| Shell, layout | src/app/ |
| Product screen | features/<name>/public/<page>.vue |
| Feature composable | размещённый рядом в feature |
| 2+ consumers | services/<name>/public/ |
| UI primitive | shared/ui/ |
| Injection keys | shared/domain/ |
| Types | shared/model/ |
Стили
| Вид | Где |
|---|---|
| Global baseline | app/app.css |
| Shell layout | App.vue <style scoped> |
| Feature page | public/*.vue scoped или CSS Modules |
| SCSS (optional) | profile.vue <style lang="scss" scoped> |
| Shared UI | shared/ui/*.vue scoped |
CSS Modules: catalog-page.module.css + <style module src="…">.
Тесты
Размещённый рядом *.test.ts (Vitest, environment: "node"):
use-catalog-search.test.tscheckout.store.test.tsservices/cart/public/cart.test.ts
Компонентные тесты — опционально с @vue/test-utils.
Команды
bun run dev
bun run build
bun run dma-check # dma check .
bun run lint # biome + @derived-modular/biome-plugin
bun run test