Специальный хук поверх useLazyQuery от Apollo для большего контроля над запросами GraphQL в вашем приложении и обеспечения бесперебойной разработки.

Мотивация

Сегодня, в эпоху распределенных и гибких рабочих процессов, крайне важно поддерживать координацию между командами, разбросанными по географическим регионам, и своевременно устранять зависимости, чтобы не блокировать разработчиков. Недавно, работая над приложением для реагирования, мы столкнулись с проблемами при интеграции API-интерфейсов GraphQL, которыми управляла другая команда. Иногда сервер был недоступен или API частично работали. Чтобы все работало на нашем конце, нам нужна была какая-то резервная настройка для имитации запросов GraphQL с фиктивными данными.

Ниже приведены некоторые опробованные подходы:

  • Статические файлы JSON из файловой системы: этот метод использует fetch для загрузки статических файлов из локального каталога. Хотя этот подход может отображать пользовательский интерфейс с требуемыми данными, но требует много доработок в исходном коде компонента и модульных тестах всякий раз, когда нам нужно переключаться между фиктивными данными (выборка) и фактическим API (перехватчик useQuery). Кроме того, статические файлы не могут принимать решения, как настоящие преобразователи.
  • Mirage JS: это еще одно решение для имитации запросов API, но оно привело к тем же проблемам, что и статические файлы. Нет интеллекта распознавателей и разницы между характером фактических запросов GraphQL и REST, которые имеют одну интеллектуальную конечную точку, в отличие от REST.

Очевидно, что упомянутые выше решения нелегко масштабировать и поддерживать. Нам нужен какой-то способ динамически перенаправлять запросы GraphQL на разные серверы по мере необходимости и контролировать их на уровне отдельных запросов. Разделы ниже посвящены той же проблеме.

Демонстрационное приложение

Предполагая, что вы знакомы с основами GraphQL, я пропущу теории и сразу перейду к реализации. Исходный код доступен @git.

Есть два идентичных сервера GraphQL, которые содержат настройку GraphQL для пользователей и учетных записей. Считайте server1 рабочим сервером, а server2 — резервным фиктивным сервером. Локальная файловая система используется для хранения файлов JSON в качестве базы данных.

Базовое реагирующее приложение инициализируется в отдельном каталоге demo. В demo/src есть подкаталог с именем graphql, который содержит все файлы, связанные с GraphQL, для использования данных с сервера. Он имеет экземпляр Apollo Client и запросы для получения пользователей и учетных записей. Пока игнорируйте другие файлы.

Выбор различных серверов можно контролировать на двух уровнях:

  1. Уровень приложения: переменная env API_MOCK используется для определения значения логического заголовка запроса mock. Если true, запросы отправляются на фиктивный сервер. Такой подход позволит контролировать все запросы в приложении в одном месте. Он примет одно из трех возможных значений: «ВКЛ», «ВЫКЛ», «АВТО». Последний режим автоматически перенаправляет на резервный сервер в случае, если основной сервер выдает ошибку.
  2. Уровень запроса: файл queryMock.js хранит пары "ключ-значение" для направления любого конкретного запроса на другой сервер. Ключ должен точно соответствовать имени запроса в схеме. Значение является логическим.

Настройка Apollo-клиента

Клиент инициализируется с пользовательской опцией выборки apollo-link-http. Все запросы к серверу GraphQL перехватываются на этом уровне для динамического определения домена на основе заголовков или макетов уровня запроса.

Пользовательский хук — useQueryMod

Это оболочка поверх useLazyHook, предоставленная Apollo. Он проверяет переменную среды API_MOCK, чтобы установить фиктивный заголовок запроса. Он имеет тот же интерфейс, что и хук useLazyQuery, и обрабатывает перенаправление на фиктивный сервер за кулисами. Это упростит интеграцию с существующими приложениями с минимальными изменениями исходного кода. Еще одним преимуществом использования пользовательского хука является простота модульного тестирования, потому что мы можем напрямую имитировать пользовательский модуль хука с помощью jest, и нет необходимости оборачивать тестовый экземпляр в Apollo Context. Также можно использовать свойство fetchOptions вместо заголовков для установки пользовательских свойств в выборке. Обратитесь к документации Apollo для более подробной информации.

Возможность динамического выбора сервера на уровне отдельного запроса — очень мощный паттерн. Это дает лучший контроль над запросами GraphQL наряду с другими преимуществами, такими как простота модульного тестирования. Шаблон решает проблему имитации данных для сред разработки и тестирования, а также переключения между различными серверами (например, prod, it, uat) в готовых к производству приложениях.