Главная Веб-разработка Что такое GraphQL, как он работает и зачем понадобился

Что такое GraphQL, как он работает и зачем понадобился

от admin

Программист в кафе: «Вы приготовите стейк по моему алгоритму?» 🍽️ Официант: «У нас только готовые блюда» 📋 Программист: «Эх, REST-кухня…» 🤔

Представьте два ресторана. В первом — фиксированное меню с готовыми комбинациями блюд. Если хотите пиццу, то получите её вместе с салатом и кофе, даже если они вам не нужны 😒. Во втором ресторане шеф-повар готовит блюда индивидуально для каждого гостя, и вы можете выбрать ингредиенты на свой вкус. Вам подадут именно то, что вы заказали 😊.

В веб-разработке первый ресторан похож на REST API, а второй — на GraphQL. REST API предоставляет разработчикам фиксированные наборы данных, тогда как GraphQL позволяет запрашивать им только то, что действительно необходимо.

В этой статье мы подробно разберём GraphQL: изучим его концепцию, предназначение, ключевые преимущества и принцип работы.

Далее мы простым языком расскажем о GraphQL и его возможностях. Однако этот материал может оказаться сложным для новичков. Поэтому, перед тем как продолжить чтение, рекомендуем ознакомиться со следующими статьями:

Что такое GraphQL

GraphQL — это специализированный язык запросов для работы с данными, разработанный компанией «Фейсбук»* в 2012 году. Он решил проблему производительности мобильных приложений, которые часто получали от сервера избыточные или неполные данные. В 2015 году технология стала общедоступной, а позже перешла под управление Linux Foundation.

До GraphQL разработчики в основном использовали REST API для взаимодействия с сервером. В REST-архитектуре у каждого ресурса есть уникальный URL-адрес, а клиенты общаются с сервером через HTTP-методы: GET, POST, PUT, DELETE и другие.

Допустим, мы хотим получить информацию о постах и подписчиках пользователя. С REST API нам придётся отправить несколько запросов, что приведёт к получению избыточных данных и увеличению нагрузки на сеть.

Пример запроса:

GET /api/users/123 GET /api/users/123/posts GET /api/users/123/followers

Ниже пример ответа с данными, которые мы не запрашивали. Сервер прислал дату рождения, адрес пользователя и полное содержание постов:

// GET /api/users/123 { “id”: “123”, “name”: “Иван Петров”, “email”: “ivan@example.com”, “birthDate”: “1990-01-01”, // 🚫 Избыточные данные “address”: “ул. Пушкина, д. 10, г. Москва, Россия” // 🚫 Избыточные данные } // GET /api/users/123/posts [ { “id”: “1”, “title”: “Мой первый пост”, “content”: “Здесь содержание первого поста…” }, // 🚫 Избыточные данные (content) { “id”: “2”, “title”: “Второй пост”, “content”: “А это содержание второго поста…” } // 🚫 Избыточные данные (content) ] // GET /api/users/123/followers [ { “id”: “456”, “name”: “Мария Сидорова” }, { “id”: “789”, “name”: “Алексей Иванов” } ]

А вот запрос, составленный с помощью GraphQL:

query { user(id: “123”) { name email posts { title } followers { name } } }

Ответ от сервера:

{ “data”: { “user”: { “name”: “Иван Петров”, “email”: “ivan@example.com”, “posts”: [ { “title”: “Мой первый пост” }, { “title”: “Второй пост” } ], “followers”: [ { “name”: “Мария Сидорова” }, { “name”: “Алексей Иванов” } ] } } }

Зачем нужен GraphQL

GraphQL повысил производительность приложений многих компаний. К примеру, GitHub сократил количество запросов к API на 80% для некоторых страниц, а Netflix уменьшил объём передаваемых данных на 30–40%.

Помимо оптимизации запросов, GraphQL решает и другие важные задачи:

  • Упрощает интеграцию различных систем и микросервисов, создавая единый API для доступа к разным источникам данных. Например, можно объединить данные из системы управления товарами, платёжной платформы и службы доставки.
  • Ускоряет процесс разработки, позволяя адаптировать запросы под клиента без изменения серверной части. Например, мобильное приложение может запрашивать базовую информацию о пользователе, а веб-версия — расширенные данные. Это позволяет использовать один API для разных клиентов без изменений на сервере.
  • Упрощает работу с API. GraphQL использует единую точку доступа для всех запросов, что позволяет мгновенно интегрировать новую информацию в систему. Например, если к товарам в интернет-магазине добавить новую характеристику, то она сразу станет доступной для всех клиентских приложений — для этого не придётся обновлять API или создавать новые точки доступа.
  • Обеспечивает простое обновление API. Разработчики могут добавлять новые поля в схему GraphQL, не нарушая работу существующих клиентов. Это позволяет постепенно расширять функциональность API без создания новых версий или нарушения обратной совместимости. Например, если добавить поле «рейтинг» для товара, существующие приложения продолжат работать без изменений, а новые смогут использовать эту дополнительную информацию.

Преимущества GraphQL

GraphQL и REST — это не единственные технологии для работы с API и обмена данными. Вот ещё несколько популярных решений:

Каждая из перечисленных технологий обладает своими особенностями, но есть характеристики, благодаря которым разработчики часто отдают предпочтение именно GraphQL:

  • Гибкость запросов. В отличие от REST и SOAP, GraphQL позволяет клиентам запрашивать только необходимые данные, что уменьшает объём передаваемой информации и количество запросов. Например, с помощью GraphQL можно одним запросом получить профиль пользователя, его посты и список друзей. В случае с REST для этого пришлось бы выполнить несколько отдельных запросов. Пример подобных запросов мы рассмотрели в начале статьи.
  • Типизация данных. В отличие от REST, GraphQL обладает встроенной строгой системой типов, что упрощает валидацию данных и снижает вероятность ошибок при разработке. Например, если в схеме GraphQL поле age определено как целое число, сервер автоматически отклонит запрос с некорректным значением — строкой тридцать вместо числа 30.
  • Версионирование API. В отличие от REST и SOAP, GraphQL позволяет добавлять новые поля и типы без нарушения работы существующих запросов. Например, вы можете добавить поле phoneNumber к типу User в схеме GraphQL. После изменения существующие клиенты продолжат работать как прежде, а новые смогут использовать добавленное поле без создания новой версии API.
  • Производительность в сложных сценариях. По сравнению с gRPC, GraphQL эффективнее обрабатывает комплексные запросы, когда необходимо получить связанную информацию из разных источников. Например, в e-commerce-приложении GraphQL может одним запросом извлечь детали товара, информацию о его наличии, отзывы и скидки. При использовании gRPC для получения той же информации потребовалось бы несколько вызовов.

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

Как работает GraphQL

GraphQL функционирует по принципу «запрос — ответ» между клиентом и сервером:

  • На сервере создаётся схема, описывающая все доступные типы данных, поля и операции, которые можно выполнить через API.
  • Клиент формирует запрос, точно указывая необходимые данные.
  • Клиент отправляет запрос на сервер через HTTP-метод POST.
  • Сервер анализирует запрос, проверяет его соответствие схеме и выполняет нужные операции для получения данных.
  • Сервер отправляет клиенту ответ, содержащий только запрашиваемую информацию.
  • Клиент получает данные и использует их для обновления интерфейса или других операций.

Для построения запросов GraphQL используются шесть основных компонентов: поля (fields), аргументы (arguments), фрагменты (fragments), псевдонимы (aliases), переменные (variables) и директивы (directives). Рассмотрим их подробнее.

Поля (fields)

Поля в GraphQL — это запрашиваемые данные. Они определяют, какую именно информацию клиент хочет получить от сервера.

Порядок заполнения полей в GraphQL-запросе:

  • Укажите нужные поля внутри фигурных скобок после имени запроса.
  • Вложенные поля заключайте в фигурные скобки.
  • Разделяйте поля переносом строки или пробелом.
  • Не ставьте запятые между полями.

Пример:

{ user { name email posts { title content } } }

Запросим у сервера имя и email пользователя:

{ user { name email } }

Ответ сервера:

{ “data”: { “user”: { “name”: “Иван Петров”, “email”: “ivanpetrov@example.com” } } }

Читать также:
Энтузиасты сравнили производительность Python 3.13 с Python 3.12 — Tproger

Аргументы (arguments)

Аргументы помогают уточнить запрос и получить конкретные данные. С их помощью вы можете фильтровать, сортировать или ограничивать результаты запроса.

Порядок добавления аргумента в GraphQL-запрос:

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

Пример запроса с несколькими аргументами:

{ users(first: 5, status: “active”) { name email } } # Ограничиваем результат пятью активными пользователями.

Ответ сервера:

{ “data”: { “users”: [ { “name”: “Иван Петров”, “email”: “ivanpetrov@example.com” }, { “name”: “Мария Сидорова”, “email”: “mariasidorova@example.com” }, { “name”: “Алексей Иванов”, “email”: “alexeyivanov@example.com” }, { “name”: “Елена Смирнова”, “email”: “elenasmirnova@example.com” }, { “name”: “Павел Козлов”, “email”: “pavelkozlov@example.com” } ] } }

Переменные (variables)

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

Порядок использования переменной:

  • Объявите её в начале запроса, используя знак $ перед именем переменной.
  • Укажите тип переменной после двоеточия. Например: String, Int, Boolean.
  • Добавьте восклицательный знак ! после типа, если переменная обязательна.
  • В самом запросе используйте переменную, указывая её имя со знаком $.

Для примера объявим переменную типа ID, обязательную для выполнения запроса:

query getUser($id: ID!) { user(id: $id) { name email } }

После объявления переменной мы должны отправить запрос на сервер, передав значение переменной $id в отдельном объекте JSON:

{ “id”: “123” } # “123” — это предполагаемый ID пользователя, информацию о котором мы хотим получить.

Ответ сервера:

{ “data”: { “user”: { “name”: “Иван Петров”, “email”: “ivanpetrov@example.com” } } }

Фрагменты (fragments)

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

Порядок создания фрагмента:

  • Используйте ключевое слово fragment, за которым должно последовать имя фрагмента.
  • Укажите тип, на котором определён фрагмент. Для этого используйте ключевое слово on.
  • В фигурных скобках перечислите поля, которые должны быть включены во фрагмент.

Пример создания фрагмента:

fragment UserBasicInfo on User { id name email }

Чтобы использовать фрагмент в запросе, добавьте три точки перед его именем:

query { user(id: “123”) { …UserBasicInfo age } } # Используем поля из фрагмента UserBasicInfo и поле age.

Ответ от сервера:

{ “data”: { “user”: { “id”: “123”, “name”: “Иван Петров”, “email”: “ivanpetrov@example.com”, “age”: 30 } } } # Мы получили поля id, name и email из фрагмента UserBasicInfo, а также дополнительное поле age.

Псевдонимы (aliases)

Псевдонимы позволяют в одном запросе получить данные для нескольких пользователей, присваивая уникальные имена каждому результату. Это упрощает структуру запросов, улучшает читаемость ответов и помогает избежать конфликтов имён при запросе одинаковых полей для разных объектов.

Порядок создания псевдонима:

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

Пример создания псевдонимов:

{ userInfo: user(id: “123”) { fullName: name contactEmail: email } } # userInfo — псевдоним для запроса user. # fullName — для поля name. # contactEmail — для поля email.

Ответ сервера на запрос с псевдонимами:

{ “data”: { “userInfo”: { “fullName”: “Иван Петров”, “contactEmail”: “ivanpetrov@example.com” } } }

Директивы (directives)

Директивы — это инструменты, управляющие выполнением запроса. Они позволяют гибко включать или исключать поля в зависимости от условий.

В GraphQL есть несколько основных типов директив:

  • @include — включает поле в результат, если условие истинно.
  • @skip — пропускает поле, если условие истинно.
  • @deprecated — помечает поле как устаревшее.
  • @specifiedBy — указывает URL спецификации для пользовательского скалярного типа.

Помимо этого, GraphQL позволяет создавать пользовательские директивы

для специфических нужд конкретного API.

Порядок создания пользовательской директивы:

  • Определите директиву в схеме GraphQL, используя ключевое слово directive.
  • Укажите имя директивы начиная с символа @.
  • Если нужно, определите аргументы директивы.
  • Укажите область применения директивы: поля (FIELD_DEFINITION), фрагменты (FRAGMENT_DEFINITION), операции (QUERY, MUTATION, SUBSCRIPTION) или другие элементы схемы (например, SCHEMA, SCALAR, OBJECT, INTERFACE, UNION, ENUM, INPUT_OBJECT).

Создадим директиву @auth, применимую к определениям полей и объектов. Эта директива принимает необязательный аргумент requires типа Role, который определяет возможные роли пользователей в системе. Если аргумент не указан, его значение по умолчанию устанавливается как USER. Такая директива позволит нам настраивать уровни доступа к различным полям или объектам в схеме GraphQL:

directive @auth(requires: Role = USER) on FIELD_DEFINITION | OBJECT enum Role { ADMIN USER GUEST }

Применим нашу директиву, добавив @auth к полю email. После этого только пользователи с ролью ADMIN смогут видеть email-адреса других пользователей:

type User { id: ID! name: String! email: String! @auth(requires: ADMIN) }

Что дальше

Для дальнейшего изучения GraphQL рекомендуем следующие ресурсы:

* Решением суда запрещена «деятельность компании Meta Platforms Inc. по реализации продуктов — социальных сетей Facebook и Instagram на территории Российской Федерации по основаниям осуществления экстремистской деятельности».

REST API — это архитектурный стиль создания веб-сервисов, использующий стандартные HTTP-методы для обмена данными между клиентом и сервером. Эти методы представляют собой стандартные команды для взаимодействия в интернете и определяют, какое действие следует выполнить с запрашиваемыми данными.

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

Точка доступа — это единый адрес, URL, через который клиенты взаимодействуют с API, получая доступ ко всем его функциям и данным.

Например, в интернет-магазине через единую точку доступа GraphQL можно одновременно запросить информацию о товаре (название, цену, описание), данные пользователя (имя, email, историю заказов) и список категорий товаров.

Схема GraphQL — это структурированное описание всех типов данных, запросов и операций, доступных в API. Она определяет, какую информацию можно запросить и как эти данные связаны между собой. Это напоминает меню в ресторане: схема GraphQL показывает, какие блюда доступны (типы данных), как их можно комбинировать (связи) и какие варианты заказа возможны (запросы и операции).

Динамический отчёт — это интерактивный документ, который автоматически обновляется и отображает актуальные данные в реальном времени. Он позволяет пользователям анализировать и визуализировать информацию, настраивая параметры под свои нужды.

Например, на складе крупного магазина электроники динамический отчёт об инвентаризации может включать следующие элементы:

— Интерактивную таблицу с текущим количеством товаров по категориям — смартфоны, ноутбуки, телевизоры и так далее.
— График с количеством продаж за выбранный период.
— Фильтры для сортировки товаров по цене, популярности или дате поступления.
— Автоматические уведомления о товарах, которые скоро закончатся.

Такой отчёт позволяет менеджерам оперативно оценивать состояние склада, прогнозировать спрос и принимать решения о пополнении запасов.

Пользовательские скалярные типы — это типы данных, расширяющие стандартный набор типов GraphQL (String, Int, Float, Boolean, ID). Разработчики определяют их самостоятельно, а директива @specifiedBy помогает документировать и стандартизировать использование этих типов. Она предоставляет ссылку на подробное описание их поведения и ограничений.

Например, если у вас есть пользовательский скалярный тип для представления даты, вы можете использовать эту директиву, чтобы указать URL, где описаны точный формат даты и правила её обработки.

Похожие статьи