falbar GraphQL для начинающих

GraphQL для начинающих

10 марта 2019 Туториал Перевод 2049 0

Сегодня очень активно обсуждаются API. А многие даже не могут дать точного определения, что такое API. По сути, API – это интерфейс программирования приложений. Это интерфейс, который позволяет людям (разработчикам, юзерам, потребителям) работать с данными.

Реклама

Вы можете представить API как бармена. Вы просите у него напиток, а он дает то, что вы попросили. Все просто. Так что же за проблемы возникают?

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

Долгое время для создания API использовался REST. С ним связаны некоторые проблемы. При создании API по дизайну REST вы столкнетесь со следующими трудностями:

  • Большое количество конечных точек;
  • Разработчикам будет гораздо труднее понимать и изучать ваш API;
  • Получение слишком большого или слишком малого количества информации.

Чтобы решить эти проблемы, Facebook создали GraphQL. Мне кажется, сейчас GraphQL – один из лучших способов создания API. Эта статья расскажет вам, почему стоит научиться этому способу уже сейчас.

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

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

Что собой представляет GraphQL?

GraphQL – это свободный язык запросов, который был разработан Facebook. Он предоставляет более действенный способ разработки, создания и использования API. По сути, это замена для REST.

GraphQL имеет большое количество возможностей, например:

  • Вы пишете, какие данные хотите получить, и получаете именно их. Вы больше не будете получать чрезмерное количество информации, как нередко бывало в REST;
  • В этом методе единственная конечная точка. Теперь не будет 2, 3 версий одного и того же API;
  • GraphQL является типизированным языком. Перед исполнением запрос должен быть описан в системе типов. Это способствует разработке более функционального API.

Это было вводное описание GraphQL. Вы узнали, почему это мощный способ создания API и почему он сейчас так популярен.

Начнем разбираться как все устроено в GraphQL

Главная цель этой статьи – не научиться создавать GraphQL сервер, так что мы не будем пока что в это углубляться. Наша цель – познакомиться с методом работы GraphQL на практике. Для этого нами будет использоваться сервер GraphQL без конфигурации – Graphpack.

В начале проекта необходимо создать новую папку. Ее название не важно. У меня она будет называться graphql-server.

В командной строке напишите:

mkdir graphql-server

На вашем ПК должен быть предустановлен NPM или Yarn. На случай, если вам неизвестно, что это: NPM и Yarn – менеджеры пакетов для языка программирования JavaScript. Для Node.js дефолтным менеджером пакетов служит NPM.

В папке проекта напишите такую команду:

npm init -y

Если же вы пользуетесь Yarn, то команда будет такой:

yarn init

NPM добавит новый файл package.json. В нем будет находиться каждая зависимость и команда.

Теперь пропишем единственную зависимость, которая нам пригодится в этом проекте.

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

В главной папке наберите в панели управления команду для установки Graphpack:

npm install --save-dev graphpack

Если вы пользуетесь Yarn, то сделайте это так:

yarn add --dev graphpack

Когда Graphpack будет установлен, проверьте скрипты в файле package.json. В него необходимо добавить такой фрагмент кода:

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

Мы создадим папку src и она будет единственной на сервере.

Создайте папку с названием src. В ней мы добавим лишь 3 файла.

В папке src необходимо создать файл под названием schema.graphql. В этом файле добавьте такой код:

type Query {
    hello: String
}

В упомянутом файле будет расположена вся схема работы GraphQL. Если вы не знаете, что это, то я объясню это позже. Не волнуйтесь!

Теперь добавим второй файл в папку src. Пусть его названием будет resolvers.js. В него необходимо добавить этот код:

import { users } from "./db";

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

export default resolvers;

Файл resolvers.js нужен для предоставления инструкций, которые переводят операции GraphQL в данные.

Наконец, создадим в папке src последний файл. Назовем его 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 }
];

В этом туториале мы не будем пользоваться настоящей БД. Файл db.js будет симулировать БД для обучающих целей.

Теперь папка src должна выглядеть так:

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

Если вы запустите команду npm run dev (для Yarn – yarn dev), то панель управления должна выдать такой ответ:

graphql-npm-run-dev-yarn-dev

Теперь можно перейти на localhost:4000. Это значит, что мы готовы писать первые запросы, мутации, подписки в GraphQL.

Вы увидите GraphQL Playground – мощную интегрированную среду разработки GraphQL, которая улучшает ход разработки.

Схема

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

Язык схем очень полезен, потому что он позволяет легко понять, какие типы будут использоваться в вашем API.

Типы

Типы – одна из важнейших фич GraphQL. Типы – это пользовательские объекты, которые отображают будущий облик API. Например, если вы создаете приложение-соцсеть, в вашем API будут такие типы: Posts, Likes, Groups, Users.

У типов есть поля. Поля отвечают конкретным типом данных. Например, рассмотрим тип Users. В нем должны содержаться поля name, age, email. Типы полей не приципиальны. Они всегда будут возвращать типы данных, такие как: ID, String, Float, Boolean, Int, список типов объектов или список типов пользовательских объектов.

Создадим первый тип. Перейдите в файл schema.graphql и замените тип Query, который в нем уже находится, на следующий текст:

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

Каждый пользователь User будет иметь ID, так что у него будет тип ID. У пользователя User также будет имя name и электронная почта email, так что у этих полей будет тип String. Также будет поле возраста age с типом Int. Достаточно просто, не так ли?

Что насчет ! в конце каждой строки? Наличие восклицательного знака значит, что поля не могут выдавать значения, являющиеся неопределёнными. Это значит, что все поля без исключения обязаны возвращать данные в ответ на каждый запрос. Неопределенным в типе User может быть только поле age.

В GraphQL вы столкнетесь с 3 основными концепциями:

  • Запросы (queries) – то, с помощью чего вы будете получать данные с сервера;
  • Мутации (mutations) – то, как вы будете модифицировать данные на сервере и возвращать обновленные данные (создавать, обновлять, удалять);
  • Подписки (subscriptions) – то, с помощью чего вы будете поддерживать связь с сервером в режиме реального времени.

Все это мы сейчас по порядку рассмотрим и начнем с запросов.

Запросы

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

Первым типом в GraphQL будет Query. Последующие запросы будут оказываться в этом типе. Первым делом перейдем в файл schema.graphql и опишем новый тип Query:

type Query {
    users: [User!]!
}

Все просто: запрос users будет показывать список из 1 или более пользователей Users. Неопределенные значения возвращаться не будут, так как мы использовали !. Значит, это определенный запрос. Он обязан постоянно что-либо возвращать.

Можно получить и данные о каком-то конкретном пользователе. Для этого понадобится новый запрос – user. В типе Query допишите этот блок кода:

user(id: ID!): User!

После этого он будет выглядеть так:

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

Как вы можете заметить, запросы в GraphQL способны передавать аргументы. В этом случае, чтобы запросить данные определенного пользователя, нужно передать его ID.

Вам может быть интересно: а откуда GraphQL знает, где взять данные? Поэтому-то у нас и есть файл resolvers.js. Он говорит GraphQL, как и где взять данные.

Сначала необходимо открыть файл resolvers.js и вставить db.js, который мы сделали недавно. Файл resolvers.js будет выглядеть так:

import { users } from "./db";

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

export default resolvers;

Пора сделать 1 запрос. Откройте файл resolvers.js, поменяйте замените hello. После этого тип Query станет выглядеть так:

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;

Разберемся, как все будет работать.

У каждого распознавателя запросов есть 4 аргумента. Функция user будет передавать id в качестве аргумента, после чего вернет конкретного пользователя, id которого совпадает с переданным. Достаточно просто.

Функция users будет возвращать уже существующий список пользователей.

Теперь посмотрим, хорошо ли работают запросы. Перейдите на localhost:4000 и вставьте следующий код:

query {
    users {
        id
        name
        email
        age
    }
}

Программа должна ответить вам данными всех пользователей.

Если вы хотите получить данные о конкретном пользователе:

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

Теперь узнаем, что такое мутации. Это один из наиболее важных элементов GraphQL.

Мутации

В GraphQL мутации – это то, как вы собираетесь модифицировать данные, находящиеся на сервере, и получать их обратно с учетом обновлений. По сути, это CUD (Create, Update, Delete – создание, обновление, удаление) в REST.

Мы впервые будем делать тип Mutation в GraphQL. Все мутации, созданные нами, будут оказываться в этом типе. Сначала перейдите в файл 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!
}

Вы можете понять, что у нас будет всего 3 мутации.

createUser: мы передаем ID, age, email, name. В ответ мы получим нового пользователя.

updateUser: мы передаем ID и новые email, age или name. В ответ мы получим нового пользователя.

deleteUser: мы передаем ID. В ответ мы получим нового пользователя.

Вернемся к файлу 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: "Robert", email: "robert@gmail.com", age: 21) {
        id
        name
        email
        age
    }
}

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

Наконец, ознакомимся с подписками и узнаем, почему они так важны.

Подписки

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

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

Простая подписка выглядит так:

subscription {
    users {
        id
        name
        email
        age
    }
}

Можно заметить очевидное сходство с запросами. Это действительно так. Работает же она иначе.

Когда на сервере происходит какое-либо обновление, он запустит запрос GraphQL, прописанный в подписке, и отправит результат, в котором учтено обновление, клиенту.

В представленной статье не будут подробно разбираться подписки.

Заключение

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

Реклама
Комментариев еще не оставлено
no_avatar