Derived Modular Arch
Гайды

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 variables

App.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.tsfeatures/catalog/Только catalog
use-checkout.tsfeatures/checkout/Только checkout
use-notifications.tsfeatures/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.vueapp/ — монтирование */public/* only
AppProviders.vueapp/ — provide context
catalog-page.vuefeature public/ — relative → composables
profile.vueстадия-0 — inject
cart.tsservice — framework-agnostic

public/ импортирует внутренности через относительные пути (../use-catalog.ts). Межмодульные — @/ aliases на */public/*.

Куда класть код

ЗадачаПапка
Shell, layoutsrc/app/
Product screenfeatures/<name>/public/<page>.vue
Feature composableразмещённый рядом в feature
2+ consumersservices/<name>/public/
UI primitiveshared/ui/
Injection keysshared/domain/
Typesshared/model/

Стили

ВидГде
Global baselineapp/app.css
Shell layoutApp.vue <style scoped>
Feature pagepublic/*.vue scoped или CSS Modules
SCSS (optional)profile.vue <style lang="scss" scoped>
Shared UIshared/ui/*.vue scoped

CSS Modules: catalog-page.module.css + <style module src="…">.

Тесты

Размещённый рядом *.test.ts (Vitest, environment: "node"):

  • use-catalog-search.test.ts
  • checkout.store.test.ts
  • services/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

Что дальше

On this page