Узнайте, как перенести парадигму компонуемости 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 позволяет вам сохранить эту интуицию и делать то же самое с вашими источниками данных:

  1. Явно назовите нужные вам API, микросервисы и базы данных в формате «конфигурация как код», а затем
  2. 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 без ущерба для опыта разработчиков?

  1. Он должен поддерживать различные данные, не нуждаясь в отдельном клиенте для каждого типа, и нам нужно будет иметь возможность явно определять эти зависимости данных вне кода нашего приложения — возможно, в файле конфигурации.
  2. Это должно позволить нам добавлять больше источников данных по мере необходимости,удалять устаревшие/мертвые источники из массива зависимостей и автоматически обновлять клиент, чтобы отразить эти изменения.
  3. Это должно позволить нам объединять данные из нескольких источников (API, базы данных, федерации Apollo, микросервисы и т. д.), чтобы нам вообще не приходилось выполнять JOIN в коде на внешнем интерфейсе.

Как оказалось, это именно то, что позволяет WunderGraph, с комбинацией архитектур API Gateway и BFF.

Если вы явно указываете свои зависимости API в конфигурации WunderGraph, как показано справа, здесь:

WunderGraph анализирует и объединяет эти источники данных (а не только конечные точки) в виртуальный граф с пространством имен и строит на его основе схему.

Теперь вас больше не волнует:

  1. Насколько по-разному работают ваши зависимости данных под капотом.
  2. Доставка любых сторонних клиентов на внешний интерфейс для поддержки этих различных источников данных.
  3. Как ваши команды должны общаться между доменами.

Потому что теперь у вас уже есть все зависимости данных в виде канонического слоя, единого источника достоверности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, который всегда отражает только данные, доступные только для чтения, или что-то еще — вы получаете все преимущества компоновки пользовательского интерфейса в сфере данных.

  1. Постепенное улучшение: пересматривайте код в любое время, чтобы конкретизировать его, или добавляйте новые части по мере роста потребностей бизнеса.

2. Гибкость: меняйте детали по мере необходимости, чтобы ваш набор технологий не затвердел.

3. Улучшенный сквозной опыт для разработчиков:

  • Единый источник достоверности (уровень GraphQL) для всех данных.
  • Идеально сформированный клиент с помощью генерации кода означает, что каждая команда точно знает, что они могут или не могут делать с данными (через автозаполнение в вашей среде IDE) при написании операций в виде запросов или мутаций GraphQL, что позволяет вам создавать точныйопыт, который вы хотите для своих пользователей, без проб и ошибок.
  • В сочетании с Next.js у вас могут быть готовые запросы в ваших <Suspense> boundaries, чтобы вы точно знали, что отображается в каждом из них, и какие именно запросы он выполняет под капотом. Это знание приводит к лучшему обновлению и оптимизации, потому что вы будете точно знать, где могут быть какие-либо проблемы или узкие места.

Что касается современной бессерверной веб-разработки, WunderGraph может работать на любом устройстве, поддерживающем Docker, поэтому интеграция в ваш технический стек осуществляется без проблем.

Этосильная игра WunderGraph. Компонуемость для всех зависимостей, позволяющая создавать модульные приложения с интенсивным использованием данных для современного Интернета без ущерба для удобства разработчиков.

Дополнительные материалы на PlainEnglish.io. Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Подпишитесь на нас в Twitter, LinkedIn, YouTube и Discord. Заинтересованы в Взлом роста? Ознакомьтесь с разделом Схема.