Я работаю в CrowdRiff уже полтора года, и последние 6 месяцев я перехожу от фронтенд-разработки к бэкэнд-разработке.

В настоящее время в CrowdRiff у нас есть промежуточный сервер узла, который служит одновременно прокси-сервером для микросервисов и уровнем для управления взаимодействиями с базой данных. Этот сервер использует экспресс фреймворк с библиотекой GraphQl. Перед работой с этим проектом я создал несколько REST API, но быстро влюбился в гибкость, строгую типизацию и возможности самодокументирования GraphQl.

Что такое GraphQl? 🙃

GraphQl - это язык запросов, который используется вместо REST API, который возвращает данные на основе одной POST конечной точки. Вместо нескольких конечных точек и типов запросов (GET/DELETE/PUT) GraphQl использует собственный язык запросов для взаимодействия с вашим API по одному маршруту.

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

Но как написать конечную точку, отличную от REST? Давайте изучим!

Во-первых, GraphQl привносит в node.js идею ввода ваших данных. Это означает, что вы сообщаете GraphQl, как будет выглядеть определенный набор данных. Давайте посмотрим, как может выглядеть возвращаемый объект user. Чтобы создать GraphQLObjectType, это может выглядеть так…

const {
  GraphQLInt,
  GraphQlString,
  GraphQLObjectType,
  GraphQLNonNull,
} = require('graphql/type');
const userType = new GraphQLObjectType({
  name: 'User',
  description: 'A user\'s information.',
  fields: {
    id: {
      type: new GraphQLNonNull(GraphQLInt),
      description: 'ID of the user.'
    },
    email: {
      type: new GraphQLNonNull(GraphQLString),
      description: 'Email of the user.',
    },
   },
});
module.exports = userType;
  • Сначала мы должны назвать этот тип, который мы создаем. Для простоты назовем его "Пользователь". Имена также должны быть уникальными.
  • Затем мы можем написать описание того, что представляют собой эти данные.
  • Наконец, мы указываем, какие пары ключ / значение будут в этих данных. У нас есть два поля в этой части данных, это id и email. Мы указываем, какой будет тип данных, целое число и строка для идентификатора и электронной почты соответственно.

Мы можем использовать этот тип в GraphQl query. В GraphQl есть queries (думать GET) и mutations (думать POST/PUT/DELETE).

Запрос GraphQl может выглядеть так…

const { GraphQLInt, GraphQLNonNull } = require('graphql/type');
const User = require('../models/user');
const userType = require('./userType')'
const usersQuery = {
  type: userType,
  description: 'Retrieve a user based on an ID.',
  args: {
    userId: {
      type: new GraphQLNonNull(GraphQLInt),
      description: 'ID of the user that you want to retrieve.',
  },
  resolve: (root, params, context) => {
    return User.findById(params.userId).then(user => {
      return user;
     });
   },
}
module.exports = usersQuery;

Запрос - это объект с рядом правил / информации о том, какой тип данных ожидать от запроса и какой тип данных возвращать при запросе.

  • Нам нужно определить, какой тип данных будет возвращать этот запрос, и мы скажем, что он вернет userType, который мы только что написали.
  • Мы можем написать описание того, что делает этот запрос. Это используется для полезного инструмента самодокументирования под названием GraphiQl (о котором я расскажу позже в этой статье).
  • Когда интерфейс вызывает этот запрос, мы говорим, что они ДОЛЖНЫ передать userId в качестве аргумента, и это должно быть целым числом. Если интерфейс предоставляет нам любую другую информацию, помимо той, что нам требуется, GraphQl отклонит запрос, сообщив интерфейсу, что userId должен быть целым числом и не может быть строкой.
  • Наконец, все, что мы хотим сделать после выполнения этого запроса, помещается в разрешение. В этом примере мы делаем запрос к базе данных, используя некую созданную нами модель User (в другом файле, с которым мы будем делать вид, что знакомы), а затем возвращаем найденную информацию. Эти возвращенные данные ДОЛЖНЫ быть похожими на тип, который мы определяем - в данном случае на тот userType, который мы написали ранее.

Внешний интерфейс может сделать запрос к query и запросить данные в зависимости от того, что они хотят, предоставив строку запроса. Это буквально строка в теле запроса POST. Например:

query {
  users(id: 1) {
    email,
  },
}

Допустим, с помощью приведенного выше кода мы выполняем users запрос к API. Мы предоставляем ему идентификатор 1 (в круглых скобках) и говорим в фигурных скобках после него, что хотим вернуть только адрес электронной почты этого пользователя. Если бы мы хотели, мы также могли бы добавить возвращаемый идентификатор, поскольку это часть нашего userType, который мы создали.

Теперь, когда у нас есть краткое представление о GraphQl, давайте поговорим о том, почему он мне нравится и почему он хорош для новичков.

1. Гибкость 💃

GraphQl устраняет необходимость записывать несколько конечных точек для похожих данных. Как упоминалось ранее, вместо создания конечной точки, которая возвращает различную информацию о пользователе, вы создаете одну query, в которой внешний интерфейс указывает данные, которые они хотели вернуть, и ко всему обращается одна конечная точка, которая принимает строка запроса.

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

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

2. Строгий ввод 🤖

Я не понимал идеи набора текста до того, как начал работать с GraphQl, и особенно не понимал, зачем мне это может понадобиться или почему это будет полезно. GraphQl строго типизирован, что означает, что каждая входящая часть данных и каждая возвращаемая часть данных должны быть определенного типа.

Чтобы взять наш пользовательский пример из ранее, мы установили объект userType, чтобы иметь поле с идентификатором с типом integer, электронным письмом с типом string. Эти поля могут принимать только эти значения. Сначала это казалось огромной проблемой, потому что я привык к динамической «гибкости» JavaScript. Но после того, как я потратил некоторое время на набор текста в GraphQL, это заставило меня по-настоящему понять данные, с которыми я работал, и это привело меня к пониманию и пониманию того, почему так важно иметь согласованные и надежные данные.

Одна из моих любимых вещей в GraphQl - это то, что он проверяет типы ввода за вас и обрабатывает отклонения / ошибки за вас. Для тех, кто раньше писал конечную точку REST или даже гибкие функции, вы начинаете сталкиваться с проблемами, связанными с типом данных, которые передаются во внешний интерфейс. Конечной точке может потребоваться передать ей идентификатор, но что, если внешний интерфейс передает строку? что, если он передает логическое значение? Что, если внешний интерфейс пытается передать литерал объекта? Для каждого из этих случаев вам нужно будет выписать чек, а затем ответ на эти неверные данные. Написание GraphQl со строгой типизацией сделает все это за вас.

Я добавлю, что понимание данных, с которыми я работаю, и понимание новых типов данных (GraphQl имеет типы перечислений и типы интерфейса) - это концепции, которые существуют в других языках программирования. Поскольку эти идеи исходят из других языков, это почти как мягкое введение в более сложные концепции, которые распространены в более строгих серверных веб-языках, таких как Elixir или Go.

3. Самостоятельная документация 💅

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

GraphQl поставляется в паре с инструментом под названием GraphiQl (читайте graph-👁-Ql). Это что-то вроде интерактивной игровой площадки с документацией для вашего API. В GraphiQl вы можете выполнять запросы / мутации, которые вы создаете, и просматривать полную документацию по ним, включая любые типы, которые вы получите обратно (например, наш тип пользователя). В этой документации будут использоваться все описания, которые вы предоставляете при написании типов и запросов / мутаций, поэтому важно проявлять усердие и писать их полностью!

Это позволяет быстро вносить изменения в создаваемый вами API, а ваши интерфейсные разработчики могут работать с самой последней информацией - без отставания какой-либо документации от вашего приложения. Это экономит много времени, когда вы создаете новые конечные точки и повторяете данные / информацию. GraphiQl - это невероятно большой плюс, почему мне действительно нравится работать с GraphQl как с библиотекой узлов.

Пишите серверы быстрее🏃

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

Последние мысли

Как и в любой другой библиотеке, в GraphQl есть множество правил и способов работы. Если ваш опыт веб-программирования связан с использованием только JavaScript или динамических языков, вначале это может показаться большой проблемой. Я думаю, что все правила - отличное направление для библиотеки JavaScript, потому что правила, которые реализует GraphQl, приближают сервер узла к другим более серьезным языкам веб-программирования. Я с нетерпением жду возможности написать больше GraphQl и посмотреть, как развивается экосистема по мере того, как она продолжает расти и становится все более популярной в сообществе серверной части JavaScript.

Если вам интересно увидеть более практический пример GraphQL, ознакомьтесь с моей статьей о преобразовании конечной точки REST в GraphQL!