Эта статья была рецензирована 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 и предоставляет две важные возможности:
- Построение схемы типа.
- Обслуживание запросов к этой схеме типа.
Необходимо построить схему типа 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
- Введение в библиотеку React JavaScript
- Видео: введение одностороннего потока данных
Простой Реактивный Компонент
Компоненты 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.js — это довольно новые технологии, выпущенные Facebook в виде набора проектов с открытым исходным кодом в 2015 году. Основная идея заключается в том, что пользовательский интерфейс лучше знает, какие данные ему нужны для визуализации определенного набора компонентов. , Если вы пытались выбрать другой JS-фреймворк из MVC Todo List и столкнулись с какой-либо проблемой, не стесняйтесь, напишите. Спасибо за прочтение.