Я провел выходные за изучением GraphQL, следуя замечательному руководству на howtographq l. GraphQL - это спецификация, созданная Facebook, которая позволяет интерфейсным и серверным системам говорить на общем языке в отношении схемы данных. По сути, GraphQL позволяет клиентам запрашивать требуемые данные, вместо того, чтобы иметь строгую структуру ответа, которую налагает REST.

GraphQL против REST

В RESTful API у нас есть конечная точка, соответствующая каждому ресурсу. Это приводит к тому, что клиенту приходится делать несколько запросов для сбора всех данных, необходимых для рендеринга пользовательского интерфейса. Например, для форума, подобного Hackernews, для отображения профиля пользователя нам потребуются данные пользователя (/ ‹user_id›), сообщения пользователя (/ ‹user_id› / links) и, возможно, ссылки на пользователь проголосовал за (/ ‹user_id› / голосов). Затем интерфейсная программа объединит эти данные.

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

GraphQL спешит на помощь!

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

query {
  user(id: 123) {
    name
    links {
      url
      description
    }
    votes {
      url
    }
  }
}

Приведенный выше запрос при отправке на сервер GraphQL (обычно в виде полезной нагрузки запроса POST) получит имя пользователя с id 123 вместе с url и описание размещенных ими ссылок, а также URL, за которые они проголосовали. Таким образом, он полностью решает проблему избыточной и недостаточной выборки.

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

Погружение

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

Схема

Продолжая пример с Hackernews, схема может выглядеть примерно так:

type User {
  id: ID!
  username: String!
  email: String!
}
type Vote {
  username: String!
  url: String!
}  
type Link {
  id: ID!
  url: String!
  description: String!
  votes: [Vote!]!
  postedBy: User!
}

Восклицательный знак (!) Обозначает обязательное поле. GraphQL поддерживает множество примитивных полей (String, Int, ID и т. Д.), И мы также можем использовать настраиваемые типы в качестве полей. Например, поле postedBy в Link имеет тип User. Также обратите внимание, что vote - это список значений типа Vote. Конечно, мы также могли использовать типы User и Link вместо username и url в Тип голосования, но я старался не усложнять.

Запросы

Запрос GraphQL отправляется от клиента к серверу для получения данных. Он имеет вид:

query {
  users {
    username
  }
}

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

У нас также могут быть аргументы в запросах. Более того, GraphQL также поддерживает выборку вложенных объектов. Более сложный запрос будет выглядеть так:

query {
  links (search: "reddit", first: 2) {
    description
    votes {
      username
    }
    postedBy {
      email
    }
  }
}

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

Мутации

А как насчет записи, обновления и удаления данных? GraphQL поддерживает это с помощью мутаций. Образец мутации будет:

mutation {
  createUser (username: "adesor", email: "[email protected]") {
    id
    username
  }
}

Будет создан пользователь с именем пользователя adesor и адресом электронной почты [email protected], а в ответ будут возвращены id и имя пользователя. Аккуратный! mutation, как и query, - это еще одно корневое поле, которое используется для информирования сервера о том, что он должен выполнить мутацию (а не запрос).

Определение схемы

Чтобы вышеуказанные запросы и мутации работали, нам нужно определить их на нашем сервере. Сервер GraphQL определяет все разрешенные запросы и изменения. В GraphQL есть три корневых типа: Запрос, Мутация и Подписка. Я не буду рассказывать о подписках в этом посте.

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

type Query {
  user(id: ID!): User!
  users: [User!]!
  links(search: String, first: Int): [Links!]!
}

Это позволяет клиентам запрашивать конкретного пользователя, нескольких пользователей и ссылки. Он также сообщает клиенту, что запросы users и links вернут списки User и Link соответственно, в то время как запрос user вернет одного User. Кроме того, запрос links поддерживает необязательные аргументы search и first, а запрос user имеет обязательный аргумент id.

Точно так же корневой тип мутации будет определяться как:

type Mutation {
  createUser(username: String!, email: String!): User!
}

Следовательно, клиент может создавать новых пользователей, используя мутацию createUser и передавая username и email в качестве аргументов, оба из которых являются обязательными.

Все эти запросы и изменения реализуются с помощью функций resolver, которые по сути являются функциями с тем же контрактом, что и соответствующий запрос или мутация. Например, преобразователем для мутации createUser будет функция, которая принимает строковое имя пользователя и строковое электронное письмо и возвращает объект пользователя.

Резюме

GraphQL меняет способ работы веб-приложений. Такие компании, как Facebook, Github и Pinterest, и многие другие, используют GraphQL. Он реализован почти для всех известных веб-языков и фреймворков.

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

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