Введение в GraphQL: понятия и архитектура

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

За последние годы значительный сдвиг в этой парадигме произвёл GraphQL, язык запросов с открытым исходным кодом и среда выполнения для управления API.

GraphQL разработан компанией Facebook в 2012 году, выпущен в 2015. Он разрабатывался для устранения недостатков традиционной архитектуры REST путем создания новой декларативной, управляемой клиентом и производительной системы.

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

Что такое GraphQL?

GraphQL расшифровывается как Graph Query Language, язык запросов к графам. Но в отличие от других языков запросов, таких как SQL (Structured Query Language, язык структурированных запросов), это язык не для прямого взаимодействия с базой данных, а, скорее, для определения контракта, через который клиент коммуницирует с API-сервером. Спецификация GraphQL — это открытый стандарт, описывающий правила и характеристики языка. Он также содержит инструкции по выполнению запросов GraphQL.

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

Характеристики GraphQL

В дизайне GraphQL есть несколько ключевых характеристик. Запросы GraphQL декларативны и иерархичны, а схема GraphQL строго типизирована и интроспективна.

Декларативность

Запросы GraphQL декларативны, а это значит, что клиент точно укажет интересующие поля, а ответ будет содержать только заданные свойства.

В данном примере запроса GraphQL к API гипотетической фэнтезийной игры запрашивается волшебник с идентификатором «1» и поля имени и расы этого объекта.

{
  wizard(id: "1") {
    name
    race
  }
}

В ответе, который возвращается в формате JSON, будет объект data, содержащий найденный объект волшебника, с двумя полями, указанными в запросе.

{
  "data": {
    "wizard": {
      "name": "Merlin",
      "race": "HUMAN"
    }
  }
}

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

Иерархичность

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

{
  wizard(id: "1") {
    name
    spells {
      name
      attack
    }
  }
}

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

{
  "data": {
    "wizard": {
      "name": "Merlin",
      "spells": [
        {
          "name": "Lightning Bolt",
          "attack": 2
        },
        {
          "name": "Ice Storm",
          "attack": 2
        },
        {
          "name": "Fireball",
          "attack": 3
        }
      ]
    }
  }
}

Строгая типизация

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

В этом примере создается тип объекта Spell с полями, соответствующими скалярным типам String и Int.

type Spell {
  name: String!
  attack: Int
  range: Int
}

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

Самодокументирование

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

Например, вы можете узнать больше о типе Spell, используя функцию интроспекции при помощи __schema.

{
  __schema {
    types {
      name
      kind
      description
    }
  }
}

Ответ придет в формате JSON, как и прочие ответы в GraphQL:

 {
  "data": {
    "__schema": {
      "types": [
        {
          "name": "Spell",
          "kind": "OBJECT",
          "description": "A powerful spell that a wizard can read from a scroll."
        }
      ]
    }
  }
}

Клиенториентированность

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

Архитектура GraphQL

GraphQL существует на прикладном уровне между клиентом и данными. Сервер GraphQL описывает возможности, доступные в API, а клиент описывает требования запроса.

Сервер

API GraphQL определяется с единственной конечной точкой, обычно конечной точкой /graphql, у которой есть доступ ко всем возможностям сервера GraphQL. Поскольку GraphQL — технология прикладного уровня, его можно обслуживать по любому протоколу, но чаще всего это — HTTP.

Сборка сервера GraphQL может быть написана на любом языке программирования, например, при помощи промежуточного ПО express-graphql, которое позволяет создавать GraphQL API на HTTP-сервере Node/Express. GraphQL также не зависит от баз данных, и данные для приложения могут храниться в MySQL, PostgreSQL, MongoDB или любой другой базе данных. Данные могут даже быть предоставлены путем агрегирования нескольких традиционных конечных точек REST API. Все, что имеет значение, это то, что данные определены в схеме GraphQL, которая определяет API, описывая данные, доступные для запроса.

Клиент

Запросы, отправленные на сервер GraphQL, называются документами и состоят из таких операций, как запросы (для запросов на чтение) и мутации (для запросов на запись).

Несмотря на то, что существуют продвинутые клиенты GraphQL, такие как Apollo Client или Relay от Facebook, которые предоставляют механизмы для кэширования, а также дополнительные инструменты, никаких специальных клиентов для выполнения запроса к серверу GraphQL не требуется.  Простого запроса XMLHttpRequest или fetch из веб-браузера достаточно для выполнения запросов путем отправки документа GraphQL на сервер GraphQL.

Ниже приведен пример fetch-запроса к конечной точке /graphql, который передает документ GraphQL как строку в теле запроса POST.

async function fetchWizards() {
  const response = await fetch('/graphql', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      query: `{
    wizards {
      id
      name
    },
  }`,
    }),
  })
  const wizards = await response.json()

  return wizards
}

fetchWizards()

На этот запрос вернётся ответ в формате JSON.

{
  "data": {
    "wizards": [
      { "id": "1", "name": "Merlin" },
      { "id": "2", "name": "Gandalf" }
    ]
  }
}

GraphQL и REST

GraphQL и REST не являются взаимозаменяемыми концепциями, но они решают аналогичные проблемы для приложений. REST, Representational State Transfer, представляет собой архитектурный стиль программного обеспечения для обмена данными между различными системами. RESTful API – это API, который придерживается принципов и ограничений REST, включающий отсутствие состояний, возможность кеширования, принудительное разделение задач между клиентом и сервером и наличие унифицированного интерфейса, например, через URI. GraphQL, как отмечалось ранее, является спецификацией языка запросов и среды для выполнения запросов.

У обеих систем есть преимущества и недостатки, обе используются при разработке современных API. Однако GraphQL был создан для борьбы с некоторыми предполагаемыми недостатками системы REST и для создания более эффективного, управляемого клиентом API.

  • Архитектура – REST API обычно определяется несколькими конечными точками на сервере, но GraphQL обменивается данными через одну конечную точку. Конечная точка GraphQL может возвращать сложный граф данных, для которого может потребоваться несколько запросов REST, уменьшая количество запросов по сети до одного показа.
  • Получение данных – REST API возвращает набор данных, найденных на сервере. Это может быть слишком большой объем данных, например, если для представления требуется только одно свойство из ответа. Также этого может быть недостаточно, например, когда есть конечная точка списка, которая возвращает не все запрошенные свойства. При помощи декларативных запросов GraphQL предотвращает избыточное или неполное получение данных.
  • Обработка ошибок. Поскольку GraphQL не обязательно должен обслуживаться через HTTP, нет никаких требований об использовании кодов ответов HTTP для ошибок. Обычно все конечные точки GraphQL разрешаются ответом кода 200 HTTP, а неудачные результаты будут включать свойство error вместе со свойством data в ответе. API RESTful, с другой стороны, использует различные коды HTTP уровня 400 для ошибок клиента и коды HTTP уровня 200 для успешных ответов.
  • Управление версиями. В отличие от обычного шаблона REST для конечных точек управления версиями, API-интерфейсы GraphQL стремятся к обратной совместимости и избегают критических изменений, часто выдавая /v1 или /v2 в самом URL-адресе для обозначения версии. Но можно реализовать и собственное управление версиями с помощью GraphQL или эволюционную версификацию при помощи REST, что впрочем менее конвенционально.
  • Кеширование. Кешируемость – неотъемлемая часть руководящих ограничений REST. Поскольку API-интерфейсы REST на основе HTTP состоят из нескольких конечных точек, использующих разные методы HTTP, они могут использовать преимущества существующих HTTP-конвенций для кэширования и предотвращения повторной выборки ресурсов. Т.к., по сути, каждый запрос GraphQL будет отличаться, но будет использовать одну конечную точку, он не может воспользоваться ни одним из встроенных механизмов HTTP-кеширования. Клиенты GraphQL могут использовать преимущества глобальной идентификации объектов, чтобы обеспечить простое кеширование.

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

  GraphQL REST
Описание Язык запросов для API и серверная среда выполнения. Архитектурный стиль для разработки веб-сервисов
Сбор данных Единая конечная точка HTTP, которая отвечает на детерминированные запросы Набор конечных точек HTTP, которые обычно возвращают предварительно определенный набор данных.
Управление версиями Не рекомендовано Общее управление версиями
Коды статуса HTTP Все виды, включая ошибки, обычно это коды 200 Использует коды HTTP.
Проверка Встроенная проверка метаданных Проверку нужно выполнять ручную
Документация Встроенная система типов и интроспекция. Не самодокументируется, доступны такие инструменты, как OpenAPI
Кэшировние Нет Да
Методы запросов Запросы, изменения и подписки (по протоколу POST для HTTP) Все используемые HTTP-методы (GET, POST, PATCH, PUT, DELETE и т.д.)
Тип содержимого ответа JSON Любой (JSON, XML, HTML, etc.)

Заключение

GraphQL – это язык запросов с открытым исходным кодом и среда выполнения для API. GraphQL был создан разработчиками Facebook для решения различных проблем, возникающих с традиционными REST API, таких как избыточная / недостаточная выборка данных и неэффективные сетевые запросы, путем создания декларативного языка запросов для API, управляемого клиентом.

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

Tags:

Добавить комментарий