Хорошо, это 2k18, и все хоть раз слышали о GraphQL. Может быть, от ваших коллег или даже от каких-нибудь гопников из неблагополучных районов вашего города. Шумиха вокруг GraphQL повсюду.
Вкратце, GraphQL - это язык запросов для вашего API, созданный Facebook в 2012 году и публично выпущенный в 2015 году. Он описывает возможности и требования с помощью системы типов, которую вы определяете для своих данных. Прозрачный? Конечно, все эти запросы и мутации, даже ваш дедушка уже знает и использует их. Вот почему мы не будем вдаваться в подробности об основах. Вместо этого мы начнем с добавления подписок в существующее серверное приложение.
Но что такое подписки GraphQL? Подписки - это довольно новая функция GraphQL, и хотя многие компании уже используют их в производственной среде, они все еще не включены в спецификацию GraphQL. Подписки позволяют обновлять данные об изменениях в реальном времени в стандартном синтаксисе GraphQL. Чтобы установить их, все, что вам нужно сделать, это подписаться на определенные мутации, а затем после того, как мутация будет запущена, выполнить некоторый код в своем приложении, чтобы отреагировать на это изменение.
Если вас интересуют подробности, я рекомендую выступление Ури Гольдштейна с ReactiveConf Я присутствовал несколько месяцев назад в Братиславе, Словакия.
Нет больше теории, давайте сразу перейдем к практике и создадим простой и масштабируемый сервер подписок GraphQL, используя среду Node.js Express, MongoDB в качестве базы данных и Flow.js для проверки статического типа.
Начнем с клонирования репозитория git и установки необходимых зависимостей.
git clone https://github.com/yakovlevyuri/graphql-subscriptions-server.git cd graphql-subscriptions-server cd yarn install
Я предполагал, что у вас уже установлен и запущен MongoDB. По умолчанию он работает на порту27017
, поэтому мы будем использовать тот же порт для нашего приложения.
В качестве интерактивной IDE GraphQL в браузере мы будем использовать Игровую площадку, которую вам предоставили наши друзья из Graphcool. Он обеспечивает автоматическую перезагрузку схемы и лучшую поддержку подписок GraphQL, что в нашем случае критично.
Итак, приступим к нашему серверу.
yarn start
Когда вы перейдете в браузере на http: // localhost: 8080 / Playground, вы должны войти в Playground:
Но прежде чем поиграть с ним, давайте выделим, что нам нужно для настройки сервера GraphQL с подписками.
Добавьте поддержку подписок на наш сервер GraphQL через WebSockets
Поскольку мы не можем отправлять частые обновления с сервера на клиент через HTTP, нам нужен сервер WebSocket. Чтобы создать его, мы воспользуемся пакетом subscriptions-transport-ws
, который упрощает задачу. Добавьте необходимые операторы импорта в src/index.js
import { createServer } from 'http'; import { execute, subscribe } from 'graphql'; import { SubscriptionServer } from 'subscriptions-transport-ws';
Чтобы открыть WebSocket на сервере GraphQL, мы должны заключить сервер Express в createServer
.
const app = express(); const server = createServer(app);
Теперь давайте воспользуемся обернутым сервером, чтобы настроить WebSocket для прослушивания подписок GraphQL.
server.listen(PORT, () => { new SubscriptionServer( { execute, subscribe, schema: Schema, }, { server: server, path: '/subscriptions', }, ); console.log(`GraphQL Server is now running on ${BASE_URI}`); console.log(`Subscriptions are running on ${WS_BASE_URI}/subscriptions`); });
Последнее, что нужно сделать на этом шаге, - настроить GraphQL Playground для использования только что настроенных подписок WebSocket. Мы используем его как промежуточное ПО для сервера, и пакетgraphql-playground-middleware-express
- это все, что нам нужно. Если вы используете другую серверную среду (например, Hapi или Koa), вы также найдете подходящие пакеты здесь.
Импортируйте желаемый пакет:
import expressPlayground from 'graphql-playground-middleware-express';
И настройте конечные точки:
app.get( '/playground', expressPlayground({ endpoint: '/graphql', subscriptionsEndpoint: `${WS_BASE_URI}/subscriptions`, }), );
Объявление подписок в схеме и добавление преобразователя подписок
Теперь давайте определим подписки в нашей схеме GraphQL.
// RootSubscriptions.js import { GraphQLObjectType } from 'graphql'; import NewCat from './NewCat'; import RemovedCat from './RemovedCat'; export default new GraphQLObjectType({ name: 'RootSubscription', description: 'Root Subscription', fields: { newCat: NewCat, removedCat: RemovedCat, }, });
Сразу после этого мы создадим экземпляр PubSub
для обработки тем подписки для нашего приложения.
// serverConfig.js import { PubSub } from 'graphql-subscriptions'; export const pubsub = new PubSub();
Создание преобразователя подписки очень похоже на запросы и изменения. Единственное отличие состоит в том, что вместо передачи только функции resolve
мы также передаем object
с методом subscribe
, который должен возвращать функцию asyncIterator
из PubSub
.
// newCat.js import { pubsub } from '../serverConfig'; import GraphQLCat from '../outputs/Cat'; import type { Cat } from '../types/Cat'; export default { type: GraphQLCat, subscribe: () => pubsub.asyncIterator('newCat'), resolve: (payload: Cat) => payload, };
Как только наш преобразователь подписки будет готов, мы можем начать публиковать в нем newCat
. Для этого мы просто вызываем метод PubSub
pubsub.publish('newCat', cat)
внутри мутацииaddCat
.
// addCat.js export default { ... resolve: async ( _: mixed, args: argsType, { Cat }: GraphqlContextType, ): Promise<CatType> => { const payload = { ...args, createdAt: new Date().toISOString(), }; const cat = await new Cat(payload).save(); pubsub.publish('newCat', cat); return cat; }, };
Вернемся к браузеру и, наконец, попробуем его, выполнив следующий запрос:
subscription newCat {
newCat {
id
name
nickName
description
createdAt
avatarUrl
age
}
}
Игровая площадка теперь ожидает создания нового Cat
, и как только сработает мутацияaddCat
, вы должны увидеть ее в своем окне Игровая площадка!
mutation addCat { addCat(name: "Pussie Cat", nickName: "pussie", description: "Ooops, I killed a mouse", avatarUrl: "http://tachyons.io/img/cat-720.jpg", age: 5) { id name nickName description createdAt avatarUrl age } }
Демонстрационное время
Поздравляю! Вы реализовали свои первые серверные подписки GraphQL через WebSockets! Вы можете найти полный исходный код этого примера на моем GitHub.
Кошки счастливы.
Понравился пост и хотите начать использовать GraphQL ежедневно? В настоящий момент мы ищем опытных фанатов JavaScript, которые присоединятся к нам на Kiwi.com в одном из самых красивых городов Европы - Праге. Для получения дополнительной информации свяжитесь со мной @ [email protected]