В MLS мы упорно работаем над изменением нашего пользовательского опыта, и в рамках этого редизайна мы хотели сосредоточиться на отображении большего количества данных. В настоящее время у нас много контента и статистики, за которой нужно охотиться. Цель (полностью задуманная игра слов) заключалась в том, чтобы собрать достаточно данных, чтобы:

  1. Предоставьте дополнительную информацию о матче и связанных с ним объектах, таких как клубы, соревнование и сезон.
  2. Предоставьте историю или обзор матча в целом.

По сути, мы хотели уйти от чего-то вроде этого:

Примерно так:

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

Чтобы получить информацию, необходимую только для этой 1 карточки совпадений, нам нужно получить данные из 3 разных источников, а затем организовать их в структуру, которая имеет смысл для наших клиентов. Но это всего лишь одно состояние для живых игр. У нас есть и другие состояния, которые нам нужно решить:

Все эти состояния представляют собой смесь данных из разных источников. Обработка этого в обычной среде REST потребует шлюза API, несмотря ни на что. В противном случае мы будем делать большое количество запросов на плитку матча.

Давайте разберем плитку по источникам данных:

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

Создание схемы

Самая важная часть GraphQL - это понимание ваших данных и построение хорошей схемы. Это заставляет вас понять, как ваши последующие клиенты на самом деле хотят структурировать данные, и заставляет вас учитывать каждое свойство, которое вы хотите раскрыть. Такой уровень детализации затрудняет добавление случайных данных в ответ, поскольку они не соответствуют схеме.

Обнаружение правильных границ доменов и отношений между этими доменами необходимо для успеха любого API, будь то REST или GraphQL. Знать домен, чтобы составить схему.

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

Важно отметить, что мы должны определить тип для каждого свойства в нашей структуре данных.

Инструменты торговли

Существует около миллиарда различных способов настройки сервера GraphQL, и довольно впечатляет, сколько модулей уже существует для распространенных фреймворков, таких как express, hapi и koa. (В MLS мы любим hapi.js, поэтому эта статья будет посвящена именно этому. Извините, экспресс и поклонники коа!)

yarn add hapi
yarn add graphql
yarn add graphql-server-hapi
yarn add graphql-tools

Это действительно все, что нужно для начала работы с GraphQL и Hapi. Итак, как только мы установили несколько узловых модулей, как мы соединили все точки?

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

Перво-наперво, давайте настроим наш плагин GraphQL для нашего сервера Hapi.

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

Круто, теперь у нас есть схема для подключения к нашему серверу, и мы видим, что она определяет некоторые точки данных, но как мы на самом деле подключим их к нашим резолверам? Если вы посмотрите в плагин, вы увидите, что мы передаем наши преобразователи и схему функции с именем makeExecutableSchema.

Это graphql-tools делает за вас тяжелую работу. Все, что вам нужно сделать, это передать resolvers объект, у которого есть ключ для любого Типа в вашей схеме, который должен разрешать данные из источника. В нашем случае, если мы посмотрим на точку данных highlights, вы увидите, что она разрешается в массив из Video объектов.

Если бы мы хотели вытащить эти видео с другой конечной точки, нам нужно было бы сделать для нее резолвер как таковой:

Поскольку highlights является ключом к нашему типу Match, у нас должно быть свойство Match в наших преобразователях со свойством подсветки, которое является функцией преобразователя.

Теперь мы можем запросить соответствие и его основные моменты, даже если один источник данных является базой данных, а другой - вызовом API. Это показывает, насколько гибким может быть GraphQL, когда вам нужно обрабатывать сложную агрегацию данных.

Самое интересное в этом то, что вы можете развернуть сервер GraphQL и сначала просто заставить его делать запросы к вашему существующему REST API. Таким образом, вы можете медленно перейти к извлечению прямо из базы данных или просто оставить GraphQL перед вашим существующим API (в случае, когда другие клиенты могут зависеть от существующего REST API). Это дает вам возможность переносить ваших подчиненных клиентов в зависимости от приоритета.

Это действительно круто, но как насчет КЭШИНГА !?

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

В REST мире (поймите!), Когда говорят о кешировании, часто люди имеют в виду HTTP кеширование. Он может принимать разные формы, но Varnish является примером. В HTTP кэшировании есть внешний источник, ответственный за кэширование запросов от вашего приложения и обслуживание этих кэшированных ресурсов клиентам. Это прекрасно работает, потому что почти любой запрос, который вы хотите кэшировать, является GET запросом, и его можно легко кэшировать с помощью HTTP инструментов кэширования. В мире GraphQL мы фактически делаем POST запросов вместо GET запросов.

Поскольку мы делаем POST запросов с параметрами тела, обычное HTTP программное обеспечение для кэширования практически бесполезно, поскольку оно не кэширует POST запросов на основе параметров тела. Это означает, что если вы хотите использовать GraphQL и не позволять каждому запросу полностью проходить через вашу систему, вам придется кэшировать ответы самостоятельно. К счастью для нас, с Hapi это очень просто.

У Hapi есть интересная функция под названием server methods. Серверные методы - это, по сути, способ обработки асинхронной мемоизации. Что делает их такими фантастическими, так это то, что вы можете определить любые параметры кеширования, которые поддерживает Hapi, что означает, что вы можете получить кеширование на основе Redis или любой другой вид кеширования, который вам нравится, с очень небольшим количеством строк кода.

Другим преимуществом является расширенная конфигурация, которую вы можете определить для методов сервера, таких как истечение срока для каждого метода и устаревшие тайм-ауты (которые позволяют вам повторно извлекать данные до истечения срока действия, помогая предотвратить любые клиентские запросы, не получающие кешированный ответ).

Давайте вернемся к нашим резольверам и посмотрим, как мы можем улучшить их с помощью серверных методов:

Еще несколько строк кода, и мы запомнили преобразователи GraphQL! 🎉

Важно отметить, что это кеширование по истечению срока действия, и если вы хотите отказаться от него, вам нужно будет настроить его самостоятельно. Также нет ничего, что заставляет вас использовать серверные методы, вы можете так же легко передать экземпляр redis вашему контекстному объекту, сделав его доступным для всех преобразователей. Вы также можете использовать другие API кэширования Hapi.

Надеюсь, к этому моменту все точки подключены, и вы сможете увидеть, как перейти от настройки сервера к отправке GraphQL-ответов с Hapi (включая кеширование некоторых приложений).

Я хотел бы услышать о том, как другие используют GraphQL на бэкэнде и решают такие сложные проблемы, как кеширование. Если у вас есть какие-либо вопросы о нашем опыте, пожалуйста, оставьте комментарий или напишите мне в Twitter!

Если вам интересно, как выглядит интерфейс, мой коллега, Пегги Рейзис, написала в блоге отличное сообщение, в котором подробно описывалась наша миграция через интерфейс.

Другие статьи: