Архив метки: graphql

Кратко про GraphQL

В отпуске появилось по-больше свободного времени, чтобы «оглянуться по сторонам» и заняться давно интересовавшими меня технологиями. В этой записи будет краткое резюме по GraphQL.

GraphQL — это стандарт декларирования структуры данных и способов получения данных, предложенный и реализованный Facebook.

Существует несколько реализаций GraphQL:

  1. От Facebook — http://graphql.org/code/ Тут, правда, странность в том, что базовую технологию https://github.com/graphql/graphql-js не рекомендуют к production. Там же в наборе есть Relay — в чём-то аналог Redux, заточенный на выемку данных с помощью GraphQL-запросов.
  2. От Apollo — http://www.apollostack.com/ Тут ребята постарались сделать full-stack, причем клиентская часть основана на Redux. Минус их в том, что есть задержка в реализации последних версий стандарта GraphQL: сейчас, например, нет stream, defer и пр., технологий ускоряющих работу с многостраничными данными и часто-обновлямыми элементами. Не думаю, что это прям критичный минус, но это стоит учитывать.
  3. И еще 3-4 штуки можно найти тут — https://github.com/chentsulin/awesome-graphql.

Там же можно найти библиотеки, реализующие GraphQL, на практически всех современных языках программирования, кучу различных примеров реализаций, способов визуализации запросов и пр. и пр.

Что мне понравилось в этой технологии:

1. Декларативное описание структур данных, которые можно запросить с сервера. Только посмотрите на эту красоту:

type Entity {
  _id: String
  title: String
  category: EntityCategory
}

type EntityCategory {
  _id: String
  title: String
}

type RootQuery {
  entity(_id: String): Entity
  entities(limit: Int): [Entity]
}

schema {
  query: RootQuery
}

Так мы описали, например, что с сервера можно запросить Entity с полями _id, title, category типа EntityCategory. В apollo-stack эта строка будет автоматически преобразована в стандартный объект GraphQLSchema.

2. Удобное написание функций, получающих данные (resolvers):

module.exports = {
    RootQuery: {
        entity(_, { _id }) {
            // Тут ожидается либо Promise, либо просто значение
            return vEntities.vertex(_id).then(v => v.vertex);
        },
        entities() {
            return vEntities.all().then(cursor => cursor.all());
        }
    },

    Entity: {
        // Эта функция будет вызвана, только если у Entity также запросили category. Также можно вернуть Promise, который зарезолвится с нужными данными.
        category(entity) {
            return { _id: 1, title: 'Category A' };
        }
    }
};

3. Язык запроса данных и Web UI GraphiQL (супер легко подключается к express) с очень крутой валидацией запросов и auto-complete, который учитывает текущую схему. Например, запросим только поле title у Entity по id:

{
  entity(id: "1") {
    title
  }
}

Из минусов можно отметить не очень понятную документацию на graphql.org (а вот у Apollo по тем же вопросам документация отличная) и официальная клиентская библиотека Relay, использование которой означает отказ от Redux.

Итого

Я вижу GraphQL как весьма удобную альтернативу классическому REST API: гораздо удобнее иметь одну «ручку», в которую можно слать разнообразные запросы на получение или изменение данных (тут они называются мутациями (mutation) и декларативное описание структуры данных, чем портянку из обработчиков путей типа req.get(‘/entities’), req.post(‘/entitites’), req.put(‘/entities/:entityId’) и т.д.

Также такой подход облегчает формирование единого state для react-приложений.