GraphQL для початківців

GraphQL для початківців
11 хв. читання
08 жовтня 2020

Абревіатура API означає  Application Programming Interface  (програмний інтерфейс програми). Це, як випливає з назви, інтерфейс, за допомогою якого розробники та користувачі взаємодіють з даними.

У цій статті ви познайомитеся з основами розробки API із застосуванням стандарту GraphQL.

Що таке GraphQL

GraphQL  - мова запитів з відкритим вихідним кодом, розроблена компанією Facebook. Вона створювалася як ефективніша альтернатива REST для розробки і використання програмних інтерфейсів застосунків.

GraphQL має безліч переваг, наприклад:

  1. Ви отримуєте інформацію саме в тому обсязі, в якому запитуєте. На відміну від REST, відповідь на запит не буде містити непотрібних даних.
  2. Вам буде необхідна всього одна кінцева точка, ніяких додаткових версій для єдиного API.
  3. GraphQL - сильно типізована мова, що дозволяє попередньо оцінити коректність запиту в рамках системи типів цього синтаксису, до виконання. Це дозволяє розробляти потужніші API.

З чого почати

Для того, щоб зрозуміти, як застосовувати стандарт на практиці, ми будемо використовувати сервер в базовій конфігурації -  Graphpack .

Для початку потрібно створити новий каталог для проєкту. В даному випадку ім'я каталогу буде  graphql-server, проте назва не принципова.

Відкрийте термінал і введіть:

mkdir graphql-server

На вашому комп'ютері повинен бути встановлений  npm або yarn .

Перейдіть в створений вами каталог, якщо ви ще цього не зробили і введіть команду в залежності від використовуваного менеджера:

npm init -y

або

yarn init 

npm створить файл  package.json, в якому будуть зберігатися всі створені вами залежності і команди.

Тепер необхідно встановити одну залежність, яку ми будемо використовувати в рамках цієї статті.

Graphpack  дозволяє створити сервер GraphQL з базовою конфігурацією. Ця функція дозволить продовжити роботу, не витрачаючи часу на налаштування.

Використовуючи термінал, в кореневому каталозі проєкту встановіть Graphpack за допомогою наступної команди:

npm install --save-dev graphpack

Або, якщо ви використовуєте yarn:

yarn add --dev graphpack

Після установки Graphpack перейдіть до файлу  package.json та додайте наступний код:

"scripts": {
    "dev": "graphpack",
    "build": "graphpack build"
}

Створіть на сервері каталог  src. В даному прикладі це буде єдиний каталог на сервері, в якому необхідно буде створити три файли.

В каталозі src створіть файл  schema.graphql. У цей файл додайте код:

type Query {
  hello: String
}

У цьому файлі буде знаходитися вся схема GraphQL.

Створіть другий файл в тому ж каталозі, назвіть його  resolvers.js. Додайте туди наступний код:

import { users } from "./db";

const resolvers = {
  Query: {
    hello: () => "Hello World!"
  }
};

export default resolvers;

У цьому файлі будуть розміщені інструкції щодо виконання операцій GraphQL.

Створіть третій файл,  db.js, що містить код:

export let users = [
  { id: 1, name: "John Doe", email: "john@gmail.com", age: 22 },
  { id: 2, name: "Jane Doe", email: "jane@gmail.com", age: 23 }
];

Для навчання роботі з GraphQL немає потреби використовувати справжні дані. Цей файл потрібен для симуляції звернень до бази даних.

Після виконання операцій каталог src повинен виглядати наступним чином:

src
  |--db.js
  |--resolvers.js
  |--schema.graphql

Тепер необхідно виконати команду  npm run dev для npm або  yarn dev для yarn. Термінал має вивести інформацію про успішний запуск сервера:

GraphQL для початківцівТепер можна перейти до  localhost:4000. Система готова до роботи над API на основі GraphQL. Для розробки використовується IDE  GraphQL Playground .

Схема

Для створення схем в GraphQL використовується власна мова Schema Definition Language (SDL). SDL володіє інтуїтивно зрозумілим синтаксисом і універсальна для будь-якої технології, що використовується.

Типи

Типи - одна з основних особливостей GraphQL. Це кастомні об'єкти, які визначають, як буде виглядати API. Наприклад, при розробці програмного інтерфейсу для програми, що взаємодіє з соцмережами, в API варто оголосити типи  Posts,  Users,  Likes,  Groups.

У типах є поля, які повертають певні різновиди даних. Наприклад, при створенні типу User, в нього варто включити поля  name,  email і  age. Поля типів можуть бути будь-якими і завжди повертають дані в форматі Int, Float, String, Boolean, ID, List of Object Types, або Custom Objects Types.

Щоб створити перший тип, відкрийте файл  schema.graphql і  замініть раніше прописаний там тип Query наступним кодом:

type User {
  id: ID!
  name: String!
  email: String!
  age: Int
}

Кожен запис типу User повинен мати ідентифікаційний номер, тому поле id містить дані відповідного типу. Поля  name та email містять String (змінну типу рядка символів), а  age - цілочислову змінну.

Знак оклику в кінці визначення поля означає, що це поле не може бути порожнім. Єдине поле без знаку оклику -  age.

GraphQL оперує трьома основними концепціями:

  1. queries - запити, з їх допомогою отримують дані з сервера.
  2. mutations - зміни, модифікація даних на сервері і їх оновлення.
  3. subscriptions  - підписки, методи підтримки постійного зв'язку з сервером.

Запити

Відкрийте файл  schema.graphql і додайте тип  Query:

type Query {
  users: [User!]!
}

Запит users буде повертати масив з однієї і більше записів типу User. Оскільки у визначенні використані знаки оклику, відповідь на запит не може бути порожньою.

Для отримання конкретного запису User необхідно створити відповідний запит. В даному випадку це буде запит user у типі Query. Додайте в код наступний рядок:

user(id: ID!): User!

Тепер код повинен виглядати так:

type Query {
  users: [User!]!
  user(id: ID!): User!
}

Як бачите, в запитах GraphQL можна передавати аргументи. В даному випадку для отримання конкретного запису в запиті як аргумент використовується його поле id.

Місцезнаходження даних, які будуть оброблятися у відповідності із запитом, визначається у файлі  resolvers.js. Відкрийте цей файл і імпортуйте навчальну базу даних  db.js:

import { users } from "./db";

const resolvers = {
  Query: {
    hello: () => "Hello World!"
  }
};

export default resolvers;

Потім замініть функцію  hello на user і  users:

import { users } from "./db";

const resolvers = {
  Query: {
    user: (parent, { id }, context, info) => {
      return users.find(user => user.id === id);
    },
    users: (parent, args, context, info) => {
      return users;
    }
  }
};

export default resolvers;

У кожному резолвері запиту є чотири аргументи. У запиті user як аргумент передається вміст поля id запису бази даних. Сервер повертає вміст відповідного запису. Запит  users не містить аргументів і завжди повертає весь масив цілком.

Для тестування отриманого коду перейдіть до  localhost:4000.

Наступний код повинен повернути список всіх записів  db.js:

query {
  users {
    id
    name
    email
    age
  }
}

Отримати перший запис з бази можна за допомогою цього коду:

query {
  user(id: 1) {
    id
    name
    email
    age
  }
}

Зміни (Mutations)

У GraphQL зміни - спосіб модифікувати дані на сервері і отримати оброблену інформацію. Цей процес можна розглядати як аналогічний концепції CUD (Create, Update, Delete) в стандарті REST.

Для створення зміни відкрийте файл  schema.graphql і додайте новий тип  mutation:

type Mutation {
  createUser(id: ID!, name: String!, email: String!, age: Int): User!
  updateUser(id: ID!, name: String, email: String, age: Int): User!
  deleteUser(id: ID!): User!
}

В даному випадку вказано три різних зміни:

  • createUser: Необхідно передати значення полів idname, email та age. Функція повертає запис типу User.
  • updateUser: Необхідно передати значення поля id, нове значення поля name, email або age. Функція повертає запис типу User.
  • deleteUser: Необхідно передати значення поля id. Функція повертає запис типу User.

Тепер відкрийте файл resolvers.js і нижче об'єкта Query створіть новий об'єкт mutation:

Mutation: {
    createUser: (parent, { id, name, email, age }, context, info) => {
      const newUser = { id, name, email, age };

      users.push(newUser);

      return newUser;
    },
    updateUser: (parent, { id, name, email, age }, context, info) => {
      let newUser = users.find(user => user.id === id);

      newUser.name = name;
      newUser.email = email;
      newUser.age = age;

      return newUser;
    },
    deleteUser: (parent, { id }, context, info) => {
      const userIndex = users.findIndex(user => user.id === id);

      if (userIndex === -1) throw new Error("User not found.");

      const deletedUsers = users.splice(userIndex, 1);

      return deletedUsers[0];
    }
  }

Повний код файлу  resolvers.js повинен виглядати так:

import { users } from "./db";

const resolvers = {
  Query: {
    user: (parent, { id }, context, info) => {
      return users.find(user => user.id === id);
    },
    users: (parent, args, context, info) => {
      return users;
    }
  },
  Mutation: {
    createUser: (parent, { id, name, email, age }, context, info) => {
      const newUser = { id, name, email, age };

      users.push(newUser);

      return newUser;
    },
    updateUser: (parent, { id, name, email, age }, context, info) => {
      let newUser = users.find(user => user.id === id);

      newUser.name = name;
      newUser.email = email;
      newUser.age = age;

      return newUser;
    },
    deleteUser: (parent, { id }, context, info) => {
      const userIndex = users.findIndex(user => user.id === id);

      if (userIndex === -1) throw new Error("User not found.");

      const deletedUsers = users.splice(userIndex, 1);

      return deletedUsers[0];
    }
  }
};

export default resolvers;

Зробіть запит до  localhost:4000:

mutation {
  createUser(id: 3, name: "Username", email: "name@example.com", age: 21) {
    id
    name
    email
    age
  }
}

Він повинен повернути новий запис типу  User. Спробуйте також інші функції зміни.

Підписки

Як згадувалося раніше, за допомогою підписок підтримується постійний зв'язок між клієнтами і сервером. Базова підписка виглядає наступним чином:

subscription {
  users {
    id
    name
    email
    age
  }
}

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

висновок

Стандарт GarphQL набирає популярність. В рамках опитування  State of JavaScript , проведеного серед JS-розробників, більше половини респондентів вказали, що чули про цю технологію і хотіли б з нею ознайомитися, а п'ята частина вже її використовує і не має наміру відмовлятися. Якщо вірити цьому тренду, GraphQL очікує активний розвиток. Сподіваємося, що даний матеріал дав вам загальне уявлення про GraphQL і зацікавив надалі його вивченні.

Джерело: A Beginner's Guide to GraphQL

Помітили помилку? Повідомте автору, для цього достатньо виділити текст з помилкою та натиснути Ctrl+Enter
Коментарі (0)

    Ще немає коментарів

Щоб залишити коментар необхідно авторизуватися.

Вхід / Реєстрація