Узнайте, как перенести парадигму компонуемости React в мир API, микросервисов и баз данных на основе Wundergraph, GraphQL во время сборки и шаблона BFF/API Gateway.
С помощью React/Next.js основная проблема, которую вы решаете, заключается в превращении некоторого понятия «состояние» в DOM с упором на возможность компоновки — использование небольших элементов для создания больших объектов.
Поздравляем, вы нашли последнего босса веб-разработки: создание многоразовых «блоков LEGO» из компонентов, которые можно масштабировать бесконечно. Если вы не использовали React/Next.js для этой битвы с самого начала, в какой-то момент вы неизбежно закончите тем, что повторно реализуете намного худший, специальный «React» из jQuery — и будете ответственный за его содержание.
Но создание составных пользовательских интерфейсов — это только полдела. Самый масштабируемый пользовательский интерфейс в мире был бы ничем без данныхдля отображения. Вот вторая половина: работа с API, базами данных и микросервисами. Если мы хотим полностью использовать масштабируемые модульные веб-приложения, мы не можем забывать о компонуемости и в этой проблемной области.
Здесь может помочь WunderGraph — платформа для разработки API с открытым исходным кодом. В рамках ментальной модели React вы уже привыкли перечислять все свои зависимости в package.json
файле и позволять менеджерам пакетов делать все остальное, когда вы npm install && npm start
проектируете. WunderGraph позволяет вам сохранить эту интуицию и делать то же самое с вашими источниками данных:
- Явно назовите нужные вам API, микросервисы и базы данных в формате «конфигурация как код», а затем
- WunderGraph генерирует код на стороне клиента, который предоставляет вам первоклассный безопасный доступ (через хуки Next.js/React) ко всем этим источникам данных во время работы над внешним интерфейсом.
В этом руководстве мы немного рискнем и объединим два разрозненных, очень разных API в приложении Next.js, чтобы показать, что WunderGraph (и никаких других зависимостей) работает вместе с вашим интерфейсом в качестве независимого сервера/API Gateway/. BFF, вы могли бы, по сути, написать интерфейсный код для нескольких REST, GraphQL, MySQL, Postgres, DBaaS, таких как Fauna, MongoDB и т. д., как если бы они были единым монолитом.
Прежде чем мы начнем, давайте быстро TL;DR концепцию:
Что вообще означает «композитивность» для API?
Прямо сейчас ваше взаимодействие с источниками данных полностью закодировано. Вы пишете код для выполнения вызовов конечной точки API или базы данных (с учетными данными в файле .env), а затем пишете дополнительный код. На этот раз асинхронный шаблон/клей для управления возвращаемыми данными.
Сам код правильный, «неправильно» то, что теперь вы связываете зависимость со своим кодом, а не с файлами конфигурации. Конечно, этот API погоды не является axios или react-dom (пакеты библиотеки/фреймворка), но, тем не менее, является зависимостью, и теперь сторонний API, который всегда отражает только временные данные, был привязан к вашему репо, стал частью вашего основного бизнеса, и теперь вы будете поддерживать его на протяжении всего срока его службы.
Придерживаясь аналогии с Lego: это похоже на склеивание ваших наборов. Добро пожаловать в раздутые, едва читаемые, едва поддерживаемые кодовые базы с жесткими ограничениями.
Вы будете выполнять описанное выше раз десятьв современных средних и крупных приложениях, которые разделены на множество микросервисов со сложными взаимодействиями и отдельными командами для каждого, которые могут наступать друг другу на пятки. Это даже не считая всех JOIN, которые вы будете выполнять в этих многочисленных сервисах/API, чтобы получить нужные вам данные.
Так как же может выглядеть масштабируемый подход к компонуемости API без ущерба для опыта разработчиков?
- Он должен поддерживать различные данные, не нуждаясь в отдельном клиенте для каждого типа, и нам нужно будет иметь возможность явно определять эти зависимости данных вне кода нашего приложения — возможно, в файле конфигурации.
- Это должно позволить нам добавлять больше источников данных по мере необходимости,удалять устаревшие/мертвые источники из массива зависимостей и автоматически обновлять клиент, чтобы отразить эти изменения.
- Это должно позволить нам объединять данные из нескольких источников (API, базы данных, федерации Apollo, микросервисы и т. д.), чтобы нам вообще не приходилось выполнять JOIN в коде на внешнем интерфейсе.
Как оказалось, это именно то, что позволяет WunderGraph, с комбинацией архитектур API Gateway и BFF.
Если вы явно указываете свои зависимости API в конфигурации WunderGraph, как показано справа, здесь:
WunderGraph анализирует и объединяет эти источники данных (а не только конечные точки) в виртуальный граф с пространством имен и строит на его основе схему.
Теперь вас больше не волнует:
- Насколько по-разному работают ваши зависимости данных под капотом.
- Доставка любых сторонних клиентов на внешний интерфейс для поддержки этих различных источников данных.
- Как ваши команды должны общаться между доменами.
Потому что теперь у вас уже есть все зависимости данных в виде канонического слоя, единого источника достоверности — GraphQL.
Как вы могли догадаться, дальше нужно просто написать операции (запросы/мутации GraphQL, которые WunderGraph предоставляет вам для автозаполнения в вашей IDE), чтобы получить нужные данные из этого стандартизированного уровня данных. Они компилируются в собственный клиент во время сборки, сохраняются и отображаются с помощью JSON-RPC (HTTP).
Наконец, в вашем интерфейсном коде вы используете сгенерированные клиентские хуки извлечения данных с безопасностью типов.
Конечный результат? Парадигма контейнеризации/менеджера пакетов, подобная Docker или NPM, но для источников данных. Со всеми вытекающими отсюда преимуществами:
- API, базы данных и микросервисы превратились в модульные составные кубики Lego, как и ваши компоненты пользовательского интерфейса.
- Больше не нужно раздувать код для JOIN и фильтров во внешнем интерфейсе, значительно улучшена читабельность кода и больше нет условий гонки при попытке выполнить транзакционную обработку в микросервисах.
- С конечной «конечной точкой» JSON-RPC поверх старого доброго HTTP; кэширование, разрешения, аутентификация и безопасность становятся решаемыми проблемами независимо от типа источника данных.
Но зачем придерживаться теории? Давайте погрузимся прямо в!
Приключение в подходе к API как к LEGO
Способность создавать и объединять источники данных, как если бы вы делали библиотеки, может привести вас к очень интересным местам с идеями, которые вам никогда не сможет дать ни один заурядный публичный API.
Скажем, например, что, если вы хотите узнать, какие крупнейшие музыкальные события — концерты, творческие вечера, фестивали и т. д. — исторически проводились в столице данной страны?
Шаг 1: выбор данных
Итак, здесь мы будем использовать два API: API стран и агрегатор MusicBrainz. Не стесняйтесь поиграть с Insomnia/Postman/Playgrounds и понять, какие данные вы можете обоснованно запрашивать с помощью этих API. Вы, вероятно, найдете массу дополнительных творческих вариантов использования.
Шаг 2. Быстрый запуск приложения WunderGraph + Next.js
Когда вы будете готовы двигаться дальше, используйте начальный шаблон в репозитории WunderGraph для приложения Next.js, которое использует первый в качестве шлюза BFF/API.
npx -y @wundergraph/wunderctl init — template nextjs-starter -o wg-concerts
Это создаст новый каталог проекта с именем wg-concerts (или имя папки по вашему выбору), запустит как WunderGraph (на локальном хосте: 9991), так и сервер Next.js (на локальном хосте: 3000), используя npm- полный пакет; в частности, используя псевдоним run-p для параллельного запуска обоих.
Шаг 3: Концерты Capital — Cross API Joins без кода.
Вот мясо и картошка этого руководства. Я подробно говорил о том, что объединение данных из разных источников является серьезной проблемой, когда выполняется в коде, и теперь вы воочию увидите, как WunderGraph упрощает их.
Вы можете объединить 2 ответа API — в нашем случае получить столицу страны, а затем использовать эту информациюдлязапроса концертов, которые там проходили, — вот так:
- Директива
@internal
для args означает, что хотя этот аргумент технически является «входом», он будет найден только внутри этого запроса и не должен предоставляться при вызове этой операции. - Директива
@export
работает рука об руку с@internal
, и все, что вы экспортируете (или псевдоним — для этого используется ключевое слово «as
»), должно иметь то же имя и тип, что и аргумент, который вы пометили как внутренний. _join
означает фактическую операцию JOIN:- Как вы можете заметить, ввод (запрос) этого второго запроса использует тот же аргумент, который мы пометили как внутренний на верхнем уровне этого запроса GraphQL.
- Хотя это необязательно, мы используем директиву
@transform
(а затем поле 'get
', указывающее на точную структуру данных, которая нам нужна), чтобы связать ответ второго запроса с 'концертами', потому что любой дополнительный запрос, к которому мы присоединяемся, конечно, добавит еще одна сложная, раздражающе вложенная структура, которую мы хотим упростить и сделать максимально читабельной. - Мы также (необязательно) включаем поле
relationships
для каждого концерта — чтобы получить здесьmbid
(внутренний идентификатор MusicBrainz артиста, участвующего в этом концерте), потому что мы по-прежнему хотим позже запрашивать сущность Artist отдельно (для баннеров, эскизов, биографий, и т.п. Опять же, по желанию).
Шаг 4: Получение сведений об исполнителе
Наша вторая и третья операции, соответственно, заключаются в том, чтобы получить изображение баннера артиста размером 1000x185 пикселей (из AudioDB) через его идентификатор MusicBrainz, а затем миниатюру/биографии. Это просто для того, чтобы украсить наш пользовательский интерфейс, и вы можете пропустить эти запросы, если вам нужны только детали концерта и ничего больше (возможно, потому, что ваш вариант использования вообще не нуждается в пользовательском интерфейсе).
Шаг 5: Отображение наших данных во внешнем интерфейсе
Мы на финишной прямой! Давайте не будем слишком заморачиваться, просто каждый концерт сопоставляется с <ConcertCard>
компонентами, а <NavBar>
с <Dropdown>
выбирают страну для получения концертов в ее столице. Ну и, конечно, TailwindCSS для стилизации.
Все сделано! Запустите localhost:3000
и вы увидите свое приложение.
Но прежде чем мы закончим, вот очень веская — и важная — проблема.
Что делать, если я не использую Next.js/React?
WunderGraph по-прежнему работает как простой шлюз API/BFF без автоматического создания клиентского интерфейса для выборки данных.
В этом сценарии, однако, у вас не будет доступа к хукам React с безопасным типом, которые WunderGraph генерирует для вас на стороне клиента, поэтому вам придется взять на себя больше забот — реализовать выборку данных самостоятельно, следить за безопасностью типов и выполнение внутренних вызовов GET/POST вручную.
Используя конфигурации WunderGraph по умолчанию, каждая ваша операция (файл .graphql) отображается как JSON-RPC (HTTP) по адресу:
http://localhost:9991/app/main/operations/[operation_name]
Таким образом, выборка ваших данных будет выглядеть примерно так:
Где Weather.graphql
— имя файла вашей операции.
Достижение разблокировано: компонуемость данных
Благодаря тому, что WunderGraph является частью вашего инструментария для объединения всех ваших API, баз данных и микросервисов — будь то BFF, API Gateway, View-Aggregator, который всегда отражает только данные, доступные только для чтения, или что-то еще — вы получаете все преимущества компоновки пользовательского интерфейса в сфере данных.
- Постепенное улучшение: пересматривайте код в любое время, чтобы конкретизировать его, или добавляйте новые части по мере роста потребностей бизнеса.
2. Гибкость: меняйте детали по мере необходимости, чтобы ваш набор технологий не затвердел.
3. Улучшенный сквозной опыт для разработчиков:
- Единый источник достоверности (уровень GraphQL) для всех данных.
- Идеально сформированный клиент с помощью генерации кода означает, что каждая команда точно знает, что они могут или не могут делать с данными (через автозаполнение в вашей среде IDE) при написании операций в виде запросов или мутаций GraphQL, что позволяет вам создавать точныйопыт, который вы хотите для своих пользователей, без проб и ошибок.
- В сочетании с Next.js у вас могут быть готовые запросы в ваших
<Suspense>
boundaries, чтобы вы точно знали, что отображается в каждом из них, и какие именно запросы он выполняет под капотом. Это знание приводит к лучшему обновлению и оптимизации, потому что вы будете точно знать, где могут быть какие-либо проблемы или узкие места.
Что касается современной бессерверной веб-разработки, WunderGraph может работать на любом устройстве, поддерживающем Docker, поэтому интеграция в ваш технический стек осуществляется без проблем.
Этосильная игра WunderGraph. Компонуемость для всех зависимостей, позволяющая создавать модульные приложения с интенсивным использованием данных для современного Интернета без ущерба для удобства разработчиков.
Дополнительные материалы на PlainEnglish.io. Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Подпишитесь на нас в Twitter, LinkedIn, YouTube и Discord. Заинтересованы в Взлом роста? Ознакомьтесь с разделом Схема.