🐱‍💻 Создание простого GraphQL Server с нуля 👨‍💻

Начнем с ответа на простой вопрос: что такое GraphQL?

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

Зачем мне изучать GraphQL, если я могу использовать подход RESTful? 🤷

Представьте, что в вашем распоряжении имеется следующая конечная точка REST.

mycompanydomain.org/employees

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

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

🗣 Как сделать запрос GraphQL?

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

GraphiQL 🎀 - интерфейсный инструмент запросов для тестирования нашего сервера GraphQL.

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

📝План действий:

Мы создадим простой сервер GraphQL, используя Node и Express, выполнив следующие 5 шагов:

  1. Настройте бэкэнд с помощью Node и Express.
  2. Создать схему и корневой запрос
  3. Реализация CRUD-операций с использованием Axios и JSON-сервера
  4. Тестирование с GraphiQL
  5. Мутации

👆Шаг 1:

  • Создайте новую папку на своем компьютере и назовите ее «GraphQL_sandbox».
  • Используя командную строку, CD в только что созданную папку «GraphQL_sandbox».
  • Убедитесь, что на вашем компьютере установлен Node.js, и введите следующую команду:

npm init

  • Вам будет предложено несколько простых вопросов, вы можете ответить на них или проигнорировать их. После завершения этого шага Node.js создаст файл манифеста с именем package.json, который будет отслеживать ваши зависимости.
  • Используйте следующую команду, чтобы получить необходимые пакеты: express, graphql и express-graphql.

npm i express graphql express-graphql nodemon

  • Это создаст запись в файле package.json в зависимостях. Итак, что это за пакеты:

express: это один из самых популярных и легких фреймворков для создания веб-сервера.

graphql: пакет, который позволяет нам создавать схему типа и обслуживать запросы по этой схеме типа.

express-graphql: этот пакет действует как промежуточное ПО между express и graphql.

nodemon: помогает разрабатывать приложения на основе node.js путем автоматического перезапуска приложения node при обнаружении изменений файлов в каталоге.

  • Внутри package.json создайте запись в разделе «scripts» для запуска nodemon. Должно быть так 👇

  • Создайте файл и назовите его server.js, который будет действовать как точка входа для нашего приложения. Добавьте следующий код в server.js.
const express = require("express");
const graphqlHTTP = require("express-graphql");
const schema = require('./schema');
const app = express();
// MIDDLEWARE
app.use("/graphql", graphqlHTTP({
    schema: schema,
    graphiql: true
}));
app.listen(5000, () => console.log("Server running on port 5000"));

Если вы работали с экспресс-версией, то вы должны быть знакомы с большей частью приведенного выше кода. graphqlHTTP здесь действует как промежуточное программное обеспечение и требует объекта конфигурации со схемой, которая состоит из запросов и изменений (мы обсудим позже); graphiql: true позволит нам использовать инструмент GraphiQL для тестирования наших запросов.

✌️ Шаг 2:

  • Создайте файл и назовите его schema.js (упоминается в server.js), он будет содержать все наши запросы и изменения.
const graphql = require("graphql");
// PART 1 - ES6 DESTRUCTURING
const { GraphQLObjectType,
  GraphQLString,
  GraphQLInt,
  GraphQLList,
  GraphQLNonNull,
  GraphQLSchema } = graphql;
// PART 2 - EMPLOYEE TYPE
const EmployeeType = new GraphQLObjectType({
  name: "Employee",
  fields: () => ({
     id: { type: GraphQLInt }
     name: { type: GraphQLString },
     email: { type: GraphQLString },
     age: { type: GraphQLInt }
  })
});
// PART 3 - ROOT QUERY
const RootQuery = new GraphQLObjectType({
   name: "RootQueryType",
   fields: {
      employee: {
          type: EmployeeType,
          args: {
             id: { type: GraphQLInt }
          },
          resolve(parentValue, args) {
          // Code to get data from server
          }
     }
   }
});
// PART 4 - EXPORT SCHEMA
module.exports = new GraphQLSchema({
   query: RootQuery
});
  • Часть 1. Пакет graphql позволяет нам определять схему, которая соответствует официальной спецификации и определениям. Он отвечает за синтаксический анализ нашей схемы и преобразование ее в объект JS. Этот пакет поставляется с определениями типов, которые помогут нам проверить наши поля.
  • Часть 2 - Схемы помогают нам описать, как выглядят данные в нашем запросе, они состоят из типов объектов и отношений между этими объектами, а также описывают, как мы можем связаться с сервером для извлечения / изменения данных.
  • Часть 3 - Корневой запрос - это способ описать, как пользователь может попасть на сервер для извлечения и получения данных. Это объект, который описывает, какие конечные точки доступны клиенту.
  • Часть 4 - Наконец, мы экспортируем нашу схему, на которую мы ссылались в нашей точке входа, где она передается промежуточному программному обеспечению.

👌Шаг 3:

  • У нас есть готовая схема и корневой запрос, но нам нужны данные, с которыми можно поиграть. Для этого необходимо установить два пакета - JSON-Server и Axios. JSON-Server используется для создания поддельного REST API, который мы можем использовать, а Axios - это HTTP-клиент на основе обещаний для браузера и node.js.

npm i json-server axios

  • Теперь перейдите в package.json и создайте еще одну запись в сценариях, как показано ниже. Это позволяет нам запустить json-сервер, на котором размещены наши фиктивные данные.
"scripts": {
     "serve": "nodemon server.js";
     "json:server" "json-server --watch data.json"
}
  • Создайте файл data.json и добавьте следующие данные.
{
  "employees": [
      {
       "id": 1,
       "name": "John Doe",
       "email": "[email protected]",
       "age": 32
      },
      {
       "id": 2,
       "name": "Kate Williams",
       "email": "[email protected]",
       "age": 50
      },
      {
       "id": 3,
       "name": "Linda Johnson",
       "email": "[email protected]",
       "age": 37
      }
  ]
}
  • Откройте командную строку в каталоге GrapQL_sandbox и выполните следующую команду. Это по умолчанию запустит фальшивый REST API, который мы только что создали, на порту 3000.

npm run json:server

  • Затем в schema.js используйте axios, который поможет нам выполнять операции CRUD с нашим поддельным API.
const axios = require('axios');
const RootQuery = new GraphQLObjectType({
   name: "RootQueryType",
   fields: {
      employee: {
          type: EmployeeType,
          args: {
             id: { type: GraphQLInt }
          },
          resolve(parent, args) {
             return axios.get(`http://localhost:3000/employees/${args.id}`)
.then(res => res.data)
          }
     },
      employees: {
          type: new GraphQLList(EmployeeType),
          resolve(parent, args) {
             return axios.get(`http://localhost:3000/employees`)
                   .then(res => res.data)
          }
     }  
  }
});
  • Откройте новый терминал, перейдите в папку GraphQL_Sandbox и введите следующую команду.

npm run serve

🤟Шаг 4:

  • Откройте свой любимый браузер и перейдите в http://localhost:5000/graphql
  • Теперь вы можете использовать GraphiQL IDE, которую мы обсуждали ранее, для тестирования наших запросов. Введите следующий запрос; нажмите кнопку воспроизведения, и сервер ответит соответствующей информацией.
{
  employee(id: 2) {
     name
     email
  }
}
  • Чтобы получить всех сотрудников 👨‍👩‍👧‍👧, используйте это:
{
  employees {
      name,
      email,
      age
  }
}
  • Теперь вы успешно получили соответствующую информацию. Мы вернемся к нашей схеме и рассмотрим возможность ее расширения.

🖐Шаг 5:

  • Мутации. Мутации позволяют нам изменять / вносить изменения в наши данные. Например, добавление нового сотрудника, редактирование существующей записи сотрудника, удаление записи сотрудника - все это может быть выполнено с помощью мутаций. В GraphQL нам нужно явно определить наши мутации, чтобы указать, какие данные можно добавлять, редактировать, удалять и т. Д.
  • Под нашим корневым запросом в schema.js добавьте следующий код:
// MUTATIONS
const mutation = new GraphQLObjectType({
  name: "Mutation",
  fields: {
    addEmployee: {
    type: EmployeeType,
    args: {
        name: { type: new GraphQLNonNull(GraphQLString) },
        email: { type: new GraphQLNonNull(GraphQLString) },
        age: { type: new GraphQLNonNull(GraphQLInt) }
      },
      resolve(parent, args) {
        return axios
           .post(`http://localhost:3000/employees/`, {
               name: args.name,
               email: args.email,
               age: args.age
        }).then(res => res.data);
     }
  },
    editEmployee: {
        type: EmployeeType,
        args: {
          name: { type: GraphQLString },
          email: { type: GraphQLString },
          age: { type: GraphQLInt },
          id: { type: new GraphQLNonNull(GraphQLInt) }
        },
        resolve(parent, args) {
           return axios.patch(`http://localhost:3000/employees/${args.id}`, args)
.then(res => res.data);
        }
  },
    deleteEmployee: {
        type: EmployeeType,
        args: {
           id: { type: new GraphQLNonNull(GraphQLInt) }
        },
        resolve(parentValue, args) {
           return axios.delete(`http://localhost:3000/employees/${args.id}`)
.then(res => res.data);
        }
    }
 }
});
module.exports = new GraphQLSchema({
  query: RootQuery,
  mutation: mutation
});
  • Перейдите на http://localhost:5000/graphql, чтобы изменить наши фиктивные данные.
  • Чтобы проверить, добавьте нового сотрудника, набрав следующий код и нажав кнопку воспроизведения. Теперь вы должны убедиться, что у вашего поддельного API есть новая запись.
mutation {
   addEmployee(name:"Raj Kapoor", email:"[email protected]", age: 23){
      name
      email
      age
   }
}
  • Чтобы 🤹‍♂️ обновить запись сотрудника:
mutation {
   editEmployee(id: 3, age: 40){
      name
      email
      age
   }
}
  • Чтобы ❌ удалить запись о сотруднике:
mutation {
   deleteEmployee(id: 2){
      id
   }
}

🙌 Поздравляем, вы успешно создали простой сервер GraphQL и выполнили операции CRUD.