Юрий Белк – Full stack Developer (страница 7)
– вы запускаете api-ts и гоняете e2e – всё зелёное;
– переключаете на api-go и гоняете те же e2e – тесты должны пройти без изменений.
Если тесты завязаны на конкретную реализацию – это плохие e2e.
Хорошие e2e завязаны на контракт.
Минимальные договорённости по именованию и портам
Чтобы всё собиралось без «магии», вводим простые правила:
1. У каждого бэкенда свой порт по умолчанию (например: 3001/3002/3003/3004).
Но порт всегда можно переопределить через переменную окружения.
2. У каждого бэкенда общий базовый префикс API (например, без префикса или /api – главное, чтобы одинаково везде).
3. Фронтенд читает API_BASE_URL из env и не «хардкодит» адрес.
4. E2E тесты читают E2E_BASE_URL (или аналог) – один параметр, чтобы тесты знали, куда стучаться.
Это мелочи, но они экономят огромное количество времени.
0.2.8. Инструменты, которые удобно поставить для работы с монорепо
Ниже – набор программ, которые заметно упрощают жизнь. Ничего “обязательного” здесь нет, но с ними будет легче.
Для работы с Git и кодом
– VS Code – универсальный редактор для всего монорепо.
– IntelliJ IDEA – очень удобна для Spring Boot/Gradle/Maven.
– Git client (по желанию) – если вам проще визуально смотреть историю и конфликты.
Для инфраструктуры
– Docker Desktop (macOS/Windows) или Docker Engine (Linux).
– Postman или Insomnia – быстро вручную дергать API (хотя у нас будет OpenAPI и тесты).
Для работы с API-контрактом
– Плагин OpenAPI для редактора (подсветка, подсказки, валидация).
– Любой HTTP клиент в IDE (в VS Code/JetBrains есть встроенные варианты).
Для языков
– Node.js (лучше через менеджер версий), плюс pnpm.
– Python (через pyenv/uv – как удобнее).
– JDK (например, 21) для JVM-проекта.
– Go (желательно фиксировать версию в проекте).
Что мы получаем в итоге
После того как структура задана, у нас появляется понятная картина:
– В apps/ лежат разные реализации, которые можно запускать по очереди.
– В packages/shared-contract лежит единый контракт API и генерация типов/клиентов.
– В infra/ лежит общая инфраструктура, которую не нужно дублировать.
– В tests/e2e лежат тесты, которые одинаково проверяют любой бэкенд.
Эта структура – фундамент книги. Дальше мы будем добавлять функциональность (эндпоинты, модели, базы данных, авторизацию), но базовые правила останутся прежними: контракт один, тесты одни, реализаций много.
Небольшая правка по ответам из предыдущего раздела
Перед новой главой уточним два момента, чтобы дальше не было путаницы.
Где лежит контракт API и почему он один?
В общем смысле вы правы: контракт – это соглашение. Но в нашем проекте это соглашение должно быть зафиксировано в коде в одном месте, иначе оно начнёт «плавать» между реализациями.
В монорепозитории книги контракт лежит здесь:
– /packages/shared-contract/openapi.yaml
Почему он один:
– единый источник правды: фронтенд, тесты и все бэкенды сверяются с одним файлом;
– нет расхождений «в TS так, а в Go чуть иначе»;
– проще развивать API: изменения проходят через одно место и проверяются автоматически.
Где будут e2e‑тесты и почему они не должны зависеть от конкретного языка?
В нашем проекте e2e‑тесты лежат в:
– /tests/e2e
Они не зависят от языка, потому что их цель – проверять поведение системы через HTTP, то есть:
– одинаковые URL и методы,
– одинаковые статус-коды,
– одинаковые тела ответов,
– одинаковые ошибки.
То, написан сервер на Python или Java, для e2e вообще не важно – важен контракт и фактическое поведение.
Что относится к apps/, а что – к packages/?
– apps/ – запускаемые приложения (frontend и каждый бэкенд).
– packages/ – общие библиотеки/артефакты, которые переиспользуются несколькими приложениями (в нашем случае – контракт и генерация типов/клиентов).
Почему инфраструктура вынесена в infra/, а не разбросана по приложениям?
Потому что инфраструктура у нас общая. Postgres/Redis/очередь – не «часть конкретного api-ts», они нужны всем реализациям.
Если размазать infra по приложениям:
– придётся дублировать docker-compose и конфиги;
– версии сервисов начнут расходиться;
– станет сложнее запускать и поддерживать окружение.
Папка infra/ делает инфраструктуру одной, а значит – повторяемой и предсказуемой.