Специальный хук поверх 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 и запросы для получения пользователей и учетных записей. Пока игнорируйте другие файлы.
Выбор различных серверов можно контролировать на двух уровнях:
- Уровень приложения: переменная env API_MOCK используется для определения значения логического заголовка запроса mock. Если true, запросы отправляются на фиктивный сервер. Такой подход позволит контролировать все запросы в приложении в одном месте. Он примет одно из трех возможных значений: «ВКЛ», «ВЫКЛ», «АВТО». Последний режим автоматически перенаправляет на резервный сервер в случае, если основной сервер выдает ошибку.
- Уровень запроса: файл queryMock.js хранит пары "ключ-значение" для направления любого конкретного запроса на другой сервер. Ключ должен точно соответствовать имени запроса в схеме. Значение является логическим.
Настройка Apollo-клиента
Клиент инициализируется с пользовательской опцией выборки apollo-link-http. Все запросы к серверу GraphQL перехватываются на этом уровне для динамического определения домена на основе заголовков или макетов уровня запроса.
Пользовательский хук — useQueryMod
Это оболочка поверх useLazyHook, предоставленная Apollo. Он проверяет переменную среды API_MOCK, чтобы установить фиктивный заголовок запроса. Он имеет тот же интерфейс, что и хук useLazyQuery, и обрабатывает перенаправление на фиктивный сервер за кулисами. Это упростит интеграцию с существующими приложениями с минимальными изменениями исходного кода. Еще одним преимуществом использования пользовательского хука является простота модульного тестирования, потому что мы можем напрямую имитировать пользовательский модуль хука с помощью jest, и нет необходимости оборачивать тестовый экземпляр в Apollo Context. Также можно использовать свойство fetchOptions вместо заголовков для установки пользовательских свойств в выборке. Обратитесь к документации Apollo для более подробной информации.
Возможность динамического выбора сервера на уровне отдельного запроса — очень мощный паттерн. Это дает лучший контроль над запросами GraphQL наряду с другими преимуществами, такими как простота модульного тестирования. Шаблон решает проблему имитации данных для сред разработки и тестирования, а также переключения между различными серверами (например, prod, it, uat) в готовых к производству приложениях.