Перестал чинить фронт руками. Сэкономил 15 часов в неделю
Знаете то чувство, когда ты уверен, что всё работает, а прод снова падает?
На прошлой неделе я заново открыл для себя это чувство.
Локально всё летало. На стейдже ошибка. Бэкендер переименовал поле в ответе. Не сказал. Не обновил документацию.
Я узнал об этом, когда код упал. И пошёл разбираться с ошибкой вместо того, чтобы продумывать архитектуру следующего модуля.
В этот момент я понял: так больше нельзя.
После этого случая я поднял вопрос на ретро. Мы договорились: теперь изменения в контракте сначала попадают в сваггер, потом в код.
Я перебрал несколько генераторов: openapi-generator, orval, swagger-typescript-api. Остановился на @hey-api/openapi-ts. Он даёт чистый код и легко настраивается под наш стек.
Я перешёл на генерируемый API-клиент.
Это набор ручек и типов, которые генерируются на основе открытого API - yaml-файла сваггера.
Теперь я просто ввожу в терминал: npm run openapi:pull
И получаю папку api/generated/ с двумя главными файлами:
- все ручки (функции для запросов) - все типы (описания структуры данных)
Ручные правки ушли в прошлое. Вместе с ними ушли «ой, забыл поправить» и часы на синхронизацию.
Как это выглядит под капотом?
1. Скачиваю свежий openapi.yaml с бэкенда через curl 2. Генерирую клиент через @hey-api/openapi-ts 3. Коммичу и spec, и сгенерированный код
generated/ руками не трогаю. Только через генерацию.
Я описал этот подход в ридми для команды. Теперь любой новичок понимает API-слой с первого дня.
Что изменилось?
В коде всегда актуальные поля. TypeScript сам подскажет, если я ошибся в имени или типе. IDE подсвечивает ошибки на этапе написания.
Исчезла головная боль с расхождениями в контракте. Раньше я тратил часы, чтобы понять: фронт неправильно стучится или бэк неправильно отвечает?
Теперь все ручки, их назначение и типы данных лежат прямо в коде проекта. Даже сваггер открывать не нужно.
Новый разработчик на проекте? Прочитал ридми и уже знает, куда смотреть. Время на онбординг сократилось.
15 часов в неделю - это не просто цифра, а две дополнительные фичи за спринт. Или время на рефакторинг, который мы вечно откладывали.
Но куда же без подводных камней?
oneOf / anyOf. Генератор не всегда красиво обрабатывает сложные схемы. Приходится дописывать гарды.
Сваггер не совпадает с реальностью. Типы говорят одно, приходит другое. TypeScript в этом случае не просто бесполезен, он активно мешает. Единственный способ успокоить компилятор - писать проверки и as-касты.
Трансформация данных. Сгенерированные DTO - это не доменные модели. Иногда оборачиваю их в адаптеры.
Храню openapi.yaml в репозитории, чтобы сборка не падала, если бэк недоступен.
Это работает. Я возвращаться к ручному написанию ручек не планирую.
А как у вас?
Генерируете API-клиенты или всё ещё пишете руками? Если генерируете, каким инструментом пользуетесь?
Бывало, что бэк менял поле, а вы узнавали об этом на проде? Делитесь в комментариях.
· 29.06
О, была похожая проблема. На проекте была монорепа и бэк на графКЛ. В моменте все неконтролируемо разрослось и нало было что-то решать. Регением стал codegen + прекоммит хуки, проверяющие типизацию.
Для простоты с бека генерились не все возможные ручки и типы, а только те, на которые созданы документы.
Т.е. фронту требуется какая-то ручка - создаётся файл *.graphql, продимается команда на кодогенерацию и вуаля. В app/generated/index.ts появляется ручка/мутация + все типы, необходимые для нее.
Если бэк меняет поле - меняется схема, требуется выполнить кодген и при попытке запушить показываются сразу ошибки типизации благодаря хукам. Бэк стучится фронту и фронт правит как надо свою часть.
Работало отлично
0
ответить
коммент скрыт — часть юзеров считает его токсичным или некорректным
коммент удалён
· 29.06
Во, яркий пример! Звучит оч хорошо ) до сих пор по такому паттерну едете или что-то поменялось, какие-то подводные камни нашлись ?
0
ответить
коммент скрыт — часть юзеров считает его токсичным или некорректным
ответ удалён
· 29.06
Я уже там не работаю, увы. Но года полтора мы прожили так. Оттачивали, понятное дело, моменты. Но, в целом, такой паттерн работает поям отлично. И аналогично можно сделать с rtk-query, если бэк на ресте
0
ответить
коммент скрыт — часть юзеров считает его токсичным или некорректным
ответ удалён
· 29.06
Ну полтора года прожить на такой системе значит работает ) спасибо, что поделились, возьму на заметку и такую реализацию
0
ответить
коммент скрыт — часть юзеров считает его токсичным или некорректным
ответ удалён