BetaДокументация для beta‑теста, возможны ошибки и неточности.
Перейти к содержимому

Расширения FEOD для продвинутых проектов ​

Расширения для FEOD — это способ адаптации под конкретные подходы и нужды. В отличие от модификаций, они не предполагают альтернативный подход, а просто добавляют возможности или делают правила более строгими.

SSR (Server-Side Rendering) ​

FEOD изначально спроектирован так, чтобы поддерживать SSR. Для работы с ним есть готовый пример, и, что важно, ключевые отличия кроются в организации приложения.

Вместо единого App мы можем вынести отдельный уровень Server. Туда попадают части, связанные исключительно с сервером и недоступные нигде больше.

Клиент и сервер имеют отдельные точки входа:

  • entry.server.ts — точка входа сервера
  • entry.client.ts — точка входа клиента

Общая фабрика создаёт приложение, роутер и Pinia заново на каждый серверный запрос. В примере страница статическая; для серверной загрузки данных нужно также передать клиенту начальное состояние с безопасной сериализацией перед hydration.

Если же мы говорим об использовании готовых фреймворков, то вы можете использовать их встроенные возможности для SSR и не подстраиваться схожим образом.

Пример структуры для SSR ​

  • src
    • app
      • server
        • entry.server.ts
      • entry.client.ts
      • create-application.ts
      • router
      • App.vue
      • layouts
      • config
    • pages
      • index.vue
    • modules
    • common
    • globals

Dependency Injection ​

В FEOD акцент сделан на минимизацию кросс-модульных взаимодействий в пользу Inversion of Control. Одной из наиболее эффективных реализаций является Dependency Injection. Для этого можно использовать различные инструменты, например SDI (Simple Dependency Injection) или другие полноценные DI-решения.

Подход делает зависимости явными и управляемыми. Это особенно заметно, когда проект разрастается, и поддержка структуры становится критически важной.

Пример использования IoC ​

ts
// modules/Notifications/index.ts
export interface NotificationService {
  show(message: string): void
}

export function createNotifications(service: NotificationService) {
  return { success: (message: string) => service.show(message) }
}
ts
// modules/ToastUI/index.ts
export function createToastService(container: HTMLElement) {
  return {
    show(message: string) {
      const toast = document.createElement('p')
      toast.textContent = message
      container.append(toast)
    }
  }
}
ts
// app/integrations/notifications.ts
import { createNotifications } from '@/modules/Notifications'
import { createToastService } from '@/modules/ToastUI'

const container = document.querySelector<HTMLElement>('#notifications')
if (!container) throw new Error('Нет контейнера уведомлений')
export const notifications = createNotifications(createToastService(container))
notifications.success('Изменения сохранены')

Контейнер #notifications находится в HTML приложения. На каждый запуск создаётся отдельный сервис; модули не хранят общую изменяемую зависимость.

Преимущества IoC в FEOD ​

  • Явные зависимости — легко понять, от чего зависит модуль
  • Упрощённое тестирование — можно легко подменить реализации
  • Слабая связанность — модули не зависят от конкретных реализаций
  • Гибкость — можно менять реализации без изменения модулей

Интеграция с DDD (Domain-Driven Design) ​

Если в вашей команде много бэкенд-разработчиков и они привыкли мыслить в терминах DDD, FEOD легко подстраивается под этот подход. В модулях можно выделить дополнительные сущности — Entities и Adapters.

Для тех, кто знаком с DDD, назначение этих частей очевидно. Они помогают ещё чётче определять входы и выходы модуля, обеспечивая строгую структуру и понятные границы.

Пример структуры модуля с DDD ​

  • modules
    • UserManagement
      • domain
        • entities
          • User.ts
      • adapters
        • secondary
          • api
            • userApi.ts
      • index.ts

Ниже показана загрузка пользователя: адаптер преобразует ответ API в сущность. Остальные части модуля здесь опущены.

Entities в контексте FEOD ​

Entities в DDD-подходе представляют бизнес-сущности с их поведением. В FEOD они размещаются внутри модуля в папке domain/entities/.

ts
// modules/UserManagement/domain/entities/User.ts
export class User {
  constructor(readonly id: string, private email: string) {
    this.updateEmail(email)
  }

  updateEmail(email: string): void {
    const normalized = email.trim()
    if (!normalized) throw new Error('Email не может быть пустым')
    this.email = normalized
  }

  getEmail(): string {
    return this.email
  }
}

Adapters в контексте FEOD ​

Adapters обеспечивают взаимодействие модуля с внешним миром:

  • Primary adapters (входные) — UI-компоненты, которые используют модуль
  • Secondary adapters (выходные) — API-клиенты, репозитории, внешние сервисы
ts
// modules/UserManagement/adapters/secondary/api/userApi.ts
import { User } from '../../../domain/entities/User'

interface UserResponse {
  id: string
  email: string
}

export class UserApi {
  async fetchUser(id: string): Promise<User> {
    const response = await fetch(`/api/users/${encodeURIComponent(id)}`)
    if (!response.ok) throw new Error(`HTTP ${response.status}`)
    const dto: UserResponse = await response.json()
    return new User(dto.id, dto.email)
  }
}

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

Использование FEOD за пределами фронтенд-приложений ​

Открытый вопрос: можно ли использовать FEOD за пределами фронтенд-приложений? Например, в разработке инструментов для линтинга, UI-библиотек или любых других пакетов, которые сами по себе не являются фронтенд-приложениями.

Эта идея пока остаётся в стадии обсуждения и проработки. Но направление интересное: если удастся масштабировать FEOD на такие кейсы, мы получим универсальный архитектурный инструмент, применимый гораздо шире, чем просто в рамках интерфейсных проектов.

Потенциальные области применения ​

  • UI-библиотеки — организация компонентов и утилит
  • Инструменты разработки — линтеры, плагины, утилиты
  • BFF и полноценный бэкенд