Код
#статьи

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

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

Иллюстрация: Оля Ежак для Skillbox Media

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

В веб-разработке первый ресторан похож на 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": "Алексей Иванов" }
      ]
    }
  }
}

Читайте также:

Методы GET и POST в HTTP

Зачем нужен GraphQL

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

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

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

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

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

  • gRPC (gRPC remote procedure call) — это фреймворк, который применяется в микросервисной архитектуре и высоконагруженных системах, требующих максимальной производительности. Например, при потоковой передаче видео или обработке транзакций.
  • OData (open data protocol) — это протокол для стандартизации API в корпоративной среде, позволяющий фильтровать и сортировать данные через URL-параметры. С ним удобно создавать динамические отчёты для анализа продаж, инвентаризации и так далее.
  • SOAP (simple object access protocol) — это протокол для обмена данными между корпоративными сетями, базами данных и прочими системами. SOAP часто используется в банковской сфере. Например, для отправки запроса на проверку баланса счёта клиента или проведения денежного перевода.
  • Falcor — это библиотека для оптимизации передачи данных между клиентом и сервером, разработанная Netflix. Она повышает производительность веб-приложений с большими объёмами данных. Например, при просмотре каталога фильмов Falcor загружает только те данные, которые видны на экране. При дальнейшей прокрутке страницы подгружаются новые постеры и описания, а неактуальная информация очищается из памяти.

Каждая из перечисленных технологий обладает своими особенностями, но есть характеристики, благодаря которым разработчики часто отдают предпочтение именно 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"
    }
  }
}

Аргументы (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 рекомендуем следующие ресурсы:

  • Официальный сайт GraphQL — здесь вы найдёте документацию, примеры использования технологии и материалы для новичков.
  • Awesome GraphQL — это обновляемый репозиторий на GitHub с обширным списком ресурсов, библиотек и инструментов для GraphQL. Здесь вы найдёте ссылки на статьи, видео, серверные и клиентские реализации, а также примеры проектов.
  • Apollo GraphQL Tutorials — это руководство по Apollo, популярной реализации GraphQL для клиента и сервера. Apollo упрощает интеграцию GraphQL в приложения за счёт готовых решений для кэширования, управления состоянием и оптимизации запросов.

Больше интересного про код — в нашем телеграм-канале. Подписывайтесь!


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

Изучайте IT на практике — бесплатно

Курсы за 2990 0 р.

Я не знаю, с чего начать
Научитесь: Профессия Фронтенд-разработчик Узнать больше
Понравилась статья?
Да

Пользуясь нашим сайтом, вы соглашаетесь с тем, что мы используем cookies 🍪

Ссылка скопирована