Всем привет, хочу поделиться накопленными знаниями по GraphQL, которые сформировались на основе около сотни прочитанных статей/доков и месяца построения API используя GraphQL.
GraphQL — это стандарт декларирования структуры данных и способов получения данных, который выступает дополнительным слоем между клиентом и сервером.
Одной из основных фичей GraphQL является то, что структура и обьем данных определяется клиентским приложением.
Рассмотрим пример простого запроса пользователя.
Клиент точно указывает, какие данные он хочет получить, используя декларативную, графо-подобную структуру, которая очень напоминает формат JSON.
В данном случае клиент запрашивает три поля (name, email и age). Но он может запрашивать как одно поле, к примеру name, так и произвольное количество полей, которые определены в типе user на GraphQL сервере.
В таком подходе, помимо удобства, у нас уменьшается либо количество запросов, либо обьем данных на транспортном уровне.
GraphQL облегчает агрегацию данных из нескольких источников.
Давайте рассмотрим простую клиент-сервер архитектуру.
У нас есть клиентское приложение и один сервер. Транспорт данных выглядит довольно просто,
не важно, какой именно протокол передачи данных для этого используется. В случае http мы посылаем запрос и получаем ответ, все довольно просто.
Как я уже говорил, GraphQL является дополнительным слоем между клиентом и сервером, и если посмотреть на эту архитектуру, то использование GraphQL выглядит вроде как избыточно.
Но как только добавляется еще один сервис, все становится на свои места.
Сервисы могут быть написанными на любом языке программирования, взаимодействовать с разными базами данных, Sql или NoSql, могут иметь разные API. Работать при такой архитектуре становиться довольно сложно, а добавление каждого нового сервиса требует много ресурсов.
Это классическая проблема масштабирования проекта, и наверняка при работе с несколькими сервисами вы используете какой либо «API Gateway».
GraphQL и является этим стандартизированным «API Gateway». Транспорт данных клиент-сервер может выполнятся с помощью любого протокола (http, ssh, ws, cli, etc.).
Клиент запрашивает ресурсы у GraphQL сервера используя GraphQL запрос. GraphQL сервер анализирует запрос, рекурсивно проходит по графу и выполняет для каждого поля его «resolver» функцию. Когда все данные по запросу будут собраны, GraphQL сервер вернет ответ.
Важно отметить, что добавление нового сервиса не влияет на существующее приложение. За счет того, что клиент определяет, какие данные он хочет получить, можно не боясь расширять существующие типы.
GraphQL использует систему типов для описания данных.
В GraphQL поля могут быть представлены как базовыми, так и пользовательскими типами. В данном примере поле user представлено пользовательским типом User. У типа User описан набор полей, которые представлены базовыми типами.
Таким образом и реализуется графо-подобная структура неопределенного уровня вложенности.
На этом конец первой части, вторая часть добавится в скором времени. Всем спасибо!)
Ну что ж, начнем с того, что такое GraphQL?
GraphQL — это стандарт декларирования структуры данных и способов получения данных, который выступает дополнительным слоем между клиентом и сервером.
Одной из основных фичей GraphQL является то, что структура и обьем данных определяется клиентским приложением.
Рассмотрим пример простого запроса пользователя.
Клиент точно указывает, какие данные он хочет получить, используя декларативную, графо-подобную структуру, которая очень напоминает формат JSON.
В данном случае клиент запрашивает три поля (name, email и age). Но он может запрашивать как одно поле, к примеру name, так и произвольное количество полей, которые определены в типе user на GraphQL сервере.
В таком подходе, помимо удобства, у нас уменьшается либо количество запросов, либо обьем данных на транспортном уровне.
GraphQL облегчает агрегацию данных из нескольких источников.
Давайте рассмотрим простую клиент-сервер архитектуру.
У нас есть клиентское приложение и один сервер. Транспорт данных выглядит довольно просто,
не важно, какой именно протокол передачи данных для этого используется. В случае http мы посылаем запрос и получаем ответ, все довольно просто.
Как я уже говорил, GraphQL является дополнительным слоем между клиентом и сервером, и если посмотреть на эту архитектуру, то использование GraphQL выглядит вроде как избыточно.
Но как только добавляется еще один сервис, все становится на свои места.
Сервисы могут быть написанными на любом языке программирования, взаимодействовать с разными базами данных, Sql или NoSql, могут иметь разные API. Работать при такой архитектуре становиться довольно сложно, а добавление каждого нового сервиса требует много ресурсов.
Это классическая проблема масштабирования проекта, и наверняка при работе с несколькими сервисами вы используете какой либо «API Gateway».
GraphQL и является этим стандартизированным «API Gateway». Транспорт данных клиент-сервер может выполнятся с помощью любого протокола (http, ssh, ws, cli, etc.).
Клиент запрашивает ресурсы у GraphQL сервера используя GraphQL запрос. GraphQL сервер анализирует запрос, рекурсивно проходит по графу и выполняет для каждого поля его «resolver» функцию. Когда все данные по запросу будут собраны, GraphQL сервер вернет ответ.
Важно отметить, что добавление нового сервиса не влияет на существующее приложение. За счет того, что клиент определяет, какие данные он хочет получить, можно не боясь расширять существующие типы.
Система типов
GraphQL использует систему типов для описания данных.
В GraphQL поля могут быть представлены как базовыми, так и пользовательскими типами. В данном примере поле user представлено пользовательским типом User. У типа User описан набор полей, которые представлены базовыми типами.
Таким образом и реализуется графо-подобная структура неопределенного уровня вложенности.
Сравнение GraphQL API и REST API
- Зависимость от протокола передачи данных.
GraphQL не зависит от протокола передачи данных, может использовать любой (http, ws, ssh, cli, etc.)
REST базируется на http протоколе, и зависит от него.
- Единая точка входа. ( Entry point )
В GraphQL для работы с данными мы всегда обращаемся к единой точке входа — GraphQL серверу. Изменяя структуру, поля, параметры запроса мы работаем с разными данными.
В REST API каждый путь (route) представляет собой отдельную точку входа.
- Возможность возвращать разные форматы данных.
GraphQL может возвращать только JSON формат.
REST в данном случае более гибкий. REST API может возвращать данные в различных форматах — JSON, XML и т.д., это зависит от заголовков http запроса, и от самой имплементации API.
- Декларация, документация, инструменты разработки
GraphQL дает возможность написания документации непосредственно в коде (inline documentation).
В GraphQL мы можем описать любой созданный нами тип. Для этого при создании типа нужно в поле «description» описать, для чего данный тип нужен. Эту документацию умеют парсить различные утилиты, IDE, что очень упрощает работу с GraphQL.
Также, GraphQL из коробки имеет свой IDE, который работает в браузере и называется GraphiQL.
GraphiQL хранит историю запросов, подсвечивает синтаксис, подсказывает поля, которые мы можем запросить у текущего типа, парсит документацию. Это заметно упрощает написание запросов.
GraphiQL можно включить через конфигурацию GraphQL, с помощью настройки graphiql = true и перейдя по пути <имя домена>/graphiql. Либо же можно использовать одно из расширений для браузера, которые имеют практически одинаковую функциональность но разный UI.
REST не имеет подобной функциональности, но есть возможность её реализовать используя SWAGGER.
- Возможность формировать структуру и объем данных на клиенте
Cобственно, это одна из основных фичей GraphQL, формат и структура данных определяется на стороне клиента. В REST формат и структура данных жестко определены на сервере.
- Передача аргументов в запрос
Делая вывод из предыдущих пунктов, вы наверняка уже знаете ответ, за счет того что GraphQL — это единая точка входа то в GraphQL, мы имеем возможность передать аргументы на любой уровень вложенности.
В REST каждый путь представлен как отдельная точка входа, в таком случае передать аргументы мы можем только для всего запроса.
На этом конец первой части, вторая часть добавится в скором времени. Всем спасибо!)