Статьи

Обзор GraphQL: создание API списка дел с React-интерфейсом

Эта статья была рецензирована Panayiotis «pvgr» Velisarakos . Спасибо всем рецензентам SitePoint за то, что сделали контент SitePoint как можно лучше!

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

В этом уроке мы напишем небольшой сервер GraphQL, чтобы отвечать на запросы из приложения Todo List . Вы можете выбрать одно из множества приложений, но так как я сейчас работаю над проектом React, я выберу React в качестве интерфейсной среды. Однако не стесняйтесь выбирать любой другой фреймворк JavaScript, с которым вам удобно.

GraphQL

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

Это делает получение данных с сервера более эффективным для клиента. Например, представьте, что клиенту ничего не нужно, кроме title и id из реализации GraphQL , тогда он должен сделать что-то вроде этого:

 query Query { todos { id, title } } 

Который производит результирующие данные (в формате JSON):

 { "data": { "todos": [ { "id": 1446412739542, "title": "Read emails" }, { "id": 1446412740883, "title": "Buy orange" }, { "id": 1446412741215, "title": "Fix garbage" } ] } } 

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

Как видно, формат ответа описывается в запросе и определяется клиентом, а не сервером. Как указано в статье под названием «Обзор GraphQL — Начало работы с GraphQL и Node.js» ,

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

Представляем GraphQL.js

GraphQL.js является эталонной реализацией GraphQL для JavaScript и предоставляет две важные возможности:

  1. Построение схемы типа.
  2. Обслуживание запросов к этой схеме типа.

Необходимо построить схему типа GraphQL, которая сопоставляется с базой кода. В следующем коде мы определяем простую схему. Он имеет один тип и список Todo(s) (где каждый элемент имеет три поля), который разрешается до фиксированного значения. Кроме того, необходимо обработать результат запроса для этой схемы типов.

 var graphql = require ('graphql'); // Here is some dummy data to make this piece of code simpler. // It will be changeable after introducing mutation. var TODOs = [ { "id": 1446412739542, "title": "Read emails", "completed": false }, { "id": 1446412740883, "title": "Buy orange", "completed": true } ]; var TodoType = new graphql.GraphQLObjectType({ name: 'todo', fields: function () { return { id: { type: graphql.GraphQLInt }, title: { type: graphql.GraphQLString }, completed: { type: graphql.GraphQLBoolean } } } }); var queryType = new graphql.GraphQLObjectType({ name: 'Query', fields: function () { return { todos: { type: new graphql.GraphQLList(TodoType), resolve: function () { return TODOs; } } } } }); module.exports = new graphql.GraphQLSchema({ query: queryType }); 

Давайте теперь посмотрим на код файла JavaScript, который дает нам данные результата в JSON:

 var graphql = require ('graphql').graphql var express = require('express') var graphQLHTTP = require('express-graphql') var Schema = require('./schema') var query = 'query { todos { id, title, completed } }' graphql(Schema, query).then( function(result) { console.log(JSON.stringify(result)); // Prints // { // "data":{ // "todos":[ // { // "id":1446412739542, // "title":"Read emails", // "completed":false // }, // { // "id":1446412740883, // "title":"Buy orange", // "completed":true // } // ] // } // } }); var app = express() .use('/', graphQLHTTP({ schema: Schema, pretty: true })) .listen(8080, function (err) { console.log('GraphQL Server is now running on localhost:8080'); }); 

Тот же результат, который дает приведенный выше код, можно получить, запустив следующий код. cURL не обязателен для получения дополнительных преимуществ в этом примере. Это просто более простой способ извлечения данных без использования нашего примера в браузере. Обратите внимание, что если вы пользователь Windows, вы можете использовать командную строку Windows для запуска примеров cURL . Более того, здесь вы можете найти хороший ресурс, чтобы узнать, как установить cURL в вашей системе .

 $ curl -XPOST -H "Content-Type:application/graphql" -d 'query { todos { title } }' http://localhost:8080 { "data": { "todos": [ { "title": "Read emails" }, { "title": "Buy orange" } ] } } 

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

реагировать

React — это библиотека JavaScript для создания пользовательских интерфейсов, разработанная Facebook и Instagram. Многие люди предпочитают думать о React как о V в паттерне MVC . Как указано на официальном сайте ,

Мы создали React для решения одной проблемы: создание больших приложений с данными, которые со временем меняются. Это все о создании повторно используемых компонентов. На самом деле, единственное, что есть компоненты сборки.

Если вам нужно руководство по React, вы можете прочитать и посмотреть следующие ресурсы:

Простой Реактивный Компонент

Компоненты React реализуют метод render() который принимает входные данные и возвращает то, что отображать. В этом примере используется XML-подобный синтаксис под названием JSX . JSX не является обязательным и не требуется для использования React. JSX — это расширение синтаксиса JavaScript, которое похоже на XML. Вы можете использовать простое синтаксическое преобразование JSX с React.

Входные данные, переданные в компонент, могут быть доступны через render() через this.props . Простой пример того, как создать компонент React, представлен ниже, и он также доступен в виде CodePen .

 var Application = React.createClass({ render: function() { return 
{this.props.text} {this.props.id}
; } });

При наличии предыдущего кода это необработанный код JavaScript, созданный компилятором JSX.

 "use strict"; var Application = React.createClass({ displayName: "Application", render: function render() { return React.createElement( "div", null, this.props.text, this.props.id ); } }); 

простой компонент реакции

Если вы хотите больше покопаться в компонентах React, найдите минутку и посмотрите видео «Введение в состояние компонентов» .

Прохождение в нашем примере

Прежде всего нам нужен сервер (запущенный и работающий) для приема запросов GraphQL из приложения Todo List. Этот сервер уже был написан выше.

Чтобы запустить наш сервер, выполните на CLI:

 $ git clone https://github.com/sitepoint-editors/todo-graphql-server.git $ cd todo-graphql-server $ npm install $ npm start 

работает сервер локально

У вас должен быть Node v4.0.0 или выше, потому что серверный код использует функции ES2015 , которые не поддерживаются более старыми версиями.

Любые запросы POST к конечной точке /graphql теперь будут выполняться для нашей схемы GraphQL. Чтобы проверить, что все работает, введите следующий код:

 $ curl -XPOST -H "Content-Type:application/graphql" -d 'query { todos { title } }' http://localhost:8080 { "data": { "todos": [] } } 

Данные еще не сохранены. Таким образом, каждый раз, когда мы запускаем сервер, массив в памяти, в котором хранятся todo(s) становится пустым. Конечно, нам не нужен доступ только для чтения к пустому массиву. Мы должны добавить и изменить данные. Этот вид операций, которые должны иметь побочные эффекты, называются мутациями в GraphQL. Определение мутации идентично определению запроса, а также возвращает типизированное значение. Идея состоит в том, что если что-то мутировало, то оно вернуло бы все, что мутировало.

 var MutationAdd = { type: new GraphQLList(TodoType), description: 'Add a Todo', args: { title: { name: 'Todo title', type: new GraphQLNonNull(GraphQLString) } }, resolve: (root, {title}) => { TODOs.push({ id: (new Date()).getTime(), title: title, completed: false }); return TODOs; } }; var MutationType = new GraphQLObjectType({ name: 'Mutation', fields: { add: MutationAdd } }); export var Schema = new GraphQLSchema({ query: QueryType, mutation: MutationType }); 

Стрелка над ( => ) — это новый синтаксис для определения функции . Одна из самых интересных новых частей ES2015.

Как объясняется в статье под названием «Ваш первый сервер GraphQL», написанной Клэем Аллсоппом,

Значительное различие между мутацией и запросом состоит в том, что мутации обрабатываются последовательно, но запросы не дают такой гарантии (фактически, GraphQL поощряет серверы использовать присущий параллелизм независимых запросов). В спецификации GraphQL приведен пример набора мутационных запросов, которые должны обрабатываться сервером в следующем порядке:

 { first: changeTheNumber(newNumber: 1) { theNumber }, second: changeTheNumber(newNumber: 3) { theNumber }, third: changeTheNumber(newNumber: 2) { theNumber } } 

Следовательно, к концу запроса поле theNumber должно иметь значение 2 . После этого краткого представления о мутации мы наконец можем добавить одну todo на наш сервер.

 $ curl -XPOST -H "Content-Type:application/graphql" -d 'mutation { add (title: "Clean garage") { id, title } }' http://localhost:8080 { "data": { "add": [ { "id": 1446443172937, "title": "Clean garage" } ] } } 

играя с сервером

Это круто, не правда ли? У нас есть гораздо больше, кроме этой добавления мутации: toggle , toggleAll , destroy , clearCompleted . и save . Стоит отметить, что мы передаем аргументы во всех мутациях. Все поля могут принимать аргументы. Создать аргументы довольно просто, и их можно поймать в функции resolve .

В конце дня у нас есть два типа запросов:

  • один для получения ( получения ) данных с сервера;
  • один для манипулирования ( создания , обновления , удаления ) данных.

Имея работающий сервер, мы готовы использовать наш список Todo, созданный в React: форк примера React TodoMVC , как уже упоминалось в начале. Чтобы скачать его, выполните:

 $ git clone -b react-graphql https://github.com/sitepoint-editors/todomvc.git $ cd todomvc $ npm install $ node server.js 

Перейдите по http://localhost:3000 чтобы увидеть запущенное приложение. Этот код имеет два основных изменения по сравнению с исходным . Во-первых, TodoModel был изменен, чтобы достичь сервера GraphQL.

модель реагирующих компонентов

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

прокси сервера

Более того, вы можете найти демо здесь и здесь .

обзор graphql

Выводы

Как вы видели в этом руководстве, GraphQL и GraphQL.js — это довольно новые технологии, выпущенные Facebook в виде набора проектов с открытым исходным кодом в 2015 году. Основная идея заключается в том, что пользовательский интерфейс лучше знает, какие данные ему нужны для визуализации определенного набора компонентов. , Если вы пытались выбрать другой JS-фреймворк из MVC Todo List и столкнулись с какой-либо проблемой, не стесняйтесь, напишите. Спасибо за прочтение.