Когда монорепо отказывается запускаться с первой попытки

Закрыл я Cursor IDE и решил разобраться, почему Notes Server — мой многопакетный проект с бэком на Node.js, веб-клиентом на Vue и кучей микросервисов — всё ещё лежит в коме. Структура классическая: packages/server, packages/web-client, packages/embeddings-service, packages/cli-client, packages/telegram-bot-client, плюс общие типы в packages/shared. На бумаге это выглядит стройно. На практике — ада.
Сначала я пошёл по классике: открыл package.json в корне, убедился, что workspaces правильно описаны, и запустил npm install. Зависимости встали. Хорошо. Теперь нужно поднять сервер на 3000-м порту.
Но вот тут появился первый камень преткновения. В packages/server/src я нашёл два файла инициализации: один — createApp(), который регистрирует все маршруты API (/api/notes, /api-docs и остальное), второй — index.ts, который вызывает createApp() и потом добавляет ещё маршруты на ту же app. Результат — маршруты дублируются, конфликтуют, а порт 3000 слушает что-то неопределённое.
Попробовал POST на /api/notes — вернул 404. Откуда-то летит HTML из dist, 53 килобайта. Это была отстроенная Vue-сборка, которая срабатывала как catch-all. Порядок регистрации в Express имеет значение.
Второй проект в сторону — включил npm run dev:web для веб-клиента. Vite поднялся на 5173. Но тут же выяснилось: веб-приложение живёт в отдельном рабочем пространстве monorepo, и Vite нужно конфигурировать, чтобы проксировать API-запросы на http://localhost:3000. К счастью, разработчик уже предусмотрел это в vite.config.ts — proxy работал из коробки.
Теперь самое интересное: когда я запустил обе части одновременно, монорепо начал вскрывать свою хрупкую природу. IDE (я использовал Cursor) показывал ошибки в импортах из packages/shared, потому что TypeScript не знал, что shared уже скомпилирован и лежит в dist. Нужен был отдельный build-шаг перед dev-режимом. Git видел все файлы, IDE — только часть. Security-чувствительные маршруты (вроде /api/auth) были видны в исходниках, но не всегда защищены middleware.
На третий час отладки я сложил ситуацию в head: - монорепо требует дотошной сортировки зависимостей между пакетами - API-маршруты нельзя регистрировать дважды - Vite-proxy нужно тестировать перед production - JavaScript-проекты с такой архитектурой требуют скрипт-оркестратор для параллельного запуска всех сервисов
Решение нашёл в npm workspaces run dev с правильным порядком запуска в root package.json. Теперь сервер, веб-клиент и embeddings-service поднимаются одной командой.
Факт в копилку: одна из причин, почему GitHub удалось захватить рынок — это именно то, что он осознал: разработчики ненавидят разбирать чужие проекты. Потому без Git и документации ничего не работает. С ними тоже часто не работает, но хотя бы есть кого винить 😄
Метаданные
- Session ID:
- grouped_notes-server_20260225_2131
- Dev Joke
- Почему GitHub лучший друг разработчика? Потому что без него ничего не работает. С ним тоже, но хотя бы есть кого винить