Привет Мир! Сервер — это сердце любого проекта. Сегодня я расскажу, как заставить его биться, чтобы вы смогли использовать в разных целях. Начиная от SPA, мобильный платформ Android + iOS и ограничиваясь лишь вашей фантазией.

Тот кто знаком с GraphQL, в этой статье не узнает ничего нового. Тот кто спешит, может сразу заглянуть в готовый репозиторий GitHub. Тот, кто заинтересован и располагает хотя бы часом времени, сможет с нулевыми знаниями создать свой полностью рабочий GraphQL сервер и что важнее — разобраться, как это все работает, даже если вы не дружите с node.js.
Введение в GraphQL
GraphQL — это язык запросов, который разработал Facebook и анонсировал в 2015 году. Он позволяет получать данные с сервера, добавлять, удалять, редактировать записи и создавать приложение реального времени буквально на коленках.
Подготовка компьютера
Кто знаком с основами node.js, может смело пропустить этот раздел.
В первую очередь на рабочем компьютере нам понадобится последняя версия Node.js 7.7.4+
По завершению установки откройте консоль и напишите команду:
node -v
Консоль вывела v7.7.4+ ? Отлично.
Чтобы не путаться в консольных командах, я составлю компактную таблицу, которая поможет ориентироваться:
npm // пакетный менеджер, через который мы будем все устанавливать i // сокращенно от install -g // установка модуля глобально init // ручное создание файла package.json init -y // автоматическое создание файла package.json -D // установка пакетов в раздел "devDependencies" -S // установка пакетов в раздел "dependencies" package.json: "devDependencies" - раздел с модулями используемых при разработке "dependencies" - раздел с модулями используемых в продакшене
Приступим к настройке проекта. Выполните по порядку команды в консоле:
// создаст рабочую директорию mkdir test // будет выполнять последующие команды из указанной директории cd test // создаст автоматически package.json в папке test npm init -y
В процессе разработки мы сделаем много изменений, а значит будет здорово, чтобы сервер перезагружался автоматически. Для этого установим глобально пакет nodemon:
npm i -g nodemon
По умолчанию все пакеты устанавливаются локально. При глобальной установке, пакет будет доступен на любом проекте в пределах рабочего компьютера.
Настройка сервера
У вас создана папка проекта, в ней имеется файл package.json, глобально установлен nodemon , проект открыт в редакторе кода или IDE? Чудно, пока этого будет достаточно.
Откроем package.json в разделе ”scripts”, удалим строку “test” и добавим новую, чтобы получилось:
"scripts": { "dev": "nodemon ./src/main.js" },
В корне проекта создайте папку srс , а в ней 3 файла: main.js, server.js, db.js .
В файле server.js будут храниться основные настройки сервера. main.js — точка входа проекта. db.js — отдельный файл с настройками подключения к базе данных.
При написание кода, будет использоваться синтаксис es2015 (es6), поэтому понадобится Babel для компиляции es6 в es5:
// babel-preset-es2015 компилирует es6 в es5 // babel-register компилировать на ходу // babel-plugin-transform-runtime + babel-preset-stage-3 // пригодятся позже npm i -D babel-register babel-preset-es2015 babel-preset-stage-3 babel-plugin-transform-runtime
Создадим еще один файл в корне проекта .babelrc c кодом:
{ "presets": [ "es2015", "stage-3" ], "plugins": ["transform-runtime"] }
.babelrc — это файл настроек для компилятора Babel, он используется автоматически. В main.js добавим:
// babel-register будет компилировать код из server.js require('babel-register'); require('./server');
Установим пакет mongoose , который позволит взаимодействовать с MongoDB.
npm i -S mongoose
В файл db.js добавьте:
import mongoose from 'mongoose'; mongoose.Promise = global.Promise; // если подключение к БД успешно, то в консоле увидим: // 'Connected to mongo server.' mongoose.connection.on('open', function (ref) { console.log('Connected to mongo server.'); }); // если сервер не может подключится к БД, то выведет сообщение: // 'Could not connect to mongo server!' + ошибки mongoose.connection.on('error', function (err) { console.log('Could not connect to mongo server!'); console.log(err); }); // пример подключения к MongoDB // mongodb://username:password@host:port/myDataBase mongoose.connect('mongodb://localhost:27017/test');
Напомню, mongoose всего лишь мост, между сервером и базой данных. Запустить MongoDB можно в облаке или на локальной машине. Поиск в Google: free mongodb cloud поможет найти бесплатное облачный хостинг. Также обратитесь к документации mongoose.
У себя я использую локальную БД: mongodb://localhost:27017/test .
В строке подключения нет username и password, в качестве host: localhost , порт: 27017, имя базы данных: test .
Наконец, мы подошли к последнему шагу настройки сервера. Вернемся к файлу server.js и установим требуемые пакеты:
// @next - это самая последняя версия пакета npm i -S koa koa-router@next koa-bodyparser@next graphql-server-koa
В сам файл server.js скопируем код:
// koa - node.js фреймворк на базе которого запускается сервер // koa-router - маршрутизация на сервере // graphql-server-koa модуль связки, чтобы подружить Koa и GraphQL import koa from 'koa'; // koa@2 import koaRouter from 'koa-router'; // koa-router@next import koaBody from 'koa-bodyparser'; // koa-bodyparser@next import {graphqlKoa, graphiqlKoa} from 'graphql-server-koa'; // знакомство с schema ждет нас впереди // db.js - файл отвечающий за подключение к MongoDB import schema from './data/schema' import './db' const app = new koa(); const router = new koaRouter(); const PORT = 3000; // koaBody is needed just for POST. app.use(koaBody()); // POST и GET запросы будут перенаправляться в схему GraphQL router.post('/graphql', graphqlKoa({schema: schema})); router.get('/graphql', graphqlKoa({schema: schema})); // инструмент для тестирования запросов localhost:3000/graphiql router.get('/graphiql', graphiqlKoa({endpointURL: '/graphql'})); app.use(router.routes()); app.use(router.allowedMethods()); // запуск сервера app.listen(PORT, () => { console.log('Server is running on', 'localhost:' + PORT); console.log('GraphiQL dashboard', 'localhost:' + PORT + '/graphiql'); });
Настройка сервера завершена. Если вы это осилили, значит хотите увидеть результат работы. В файле server.js закомментируем три строчки кода:
//import schema from './data/schema'; //router.post('/graphql', graphqlKoa({schema: schema})); //router.get('/graphql', graphqlKoa({schema: schema}));
Мы еще не создавали схему GraphQL, поэтому так мы избежим ошибок и сможем насладиться рабочим сервером. Запустим его:
npm run dev
Если все сделали правильно и имеется подключение к MongoDB, в консоле увидим следующее:
> nodemon ./src/main.js [nodemon] 1.11.0 [nodemon] to restart at any time, enter `rs` [nodemon] watching: *.* [nodemon] starting `node ./src/main.js` Sever is running on localhost:3000 GraphiQL dashboard localhost:3000/graphiql Connected to mongo server.
В консоле ошибки? Ничего страшного. Откройте оригинальный проект на Github и сверьте файлы за исключением папок data и .idea .
Если получилось запустить без ошибок, откройте в браузере:
http://localhost:3000/graphiql
Вам будет доступен графический инструмент GraphiQL для тестирования запросов. Получилось? Отлично.
Пришло время сделать небольшой перерыв. Налейте себе кофе или чай, в зависимости от того, что вам больше нравится. Позже мы продолжим говорить о самом интересном.
2 + 2 = GraphQL
GraphQL — прост и я могу это доказать.
Недавно, вы возможно прислушались моего совета и сделали себе чай или кофе. Теперь представьте, что за вас это бы сделал некая Jane Dohe.
Так, вам нужно лишь ей сказать, что именно вы хотите: чай или кофе. Jane сможет сама приготовить и принести вам. Даже если вы предпочитаете сахар и молоко в напиток, Jane возьмет у соседки сахар, а за молоком дойдет до магазина. Сама все приготовит и уже в готовом виде принесет вам, в то самое место, где вы об этом ее попросили.
У Jane есть лишь один нюанс, сама она не знает, где брать сахар и молоко, поэтому ей нужно один раз объяснить и при любой повторной просьбе она будет это делать самостоятельно.
Именно так работает GraphQL на примере Jane Dohe. Вы отправляете запрос или запросы из любого места проекта. В тоже самое место, вы получаете ответ в формате JSON. Даже если запрашиваемые данные находятся в разных базах: MongoDB, MySQL, PostgreSQL. С одним нюансом, как и Jane, прежде чем делать запрос, нужно один раз объяснить GraphQL серверу, как готовить данные и откуда их нужно брать.
Помните, когда мы комментировали три строчки кода в server.js, чтобы запустить проект? Пора раскомментировать их обратно:
import schema from './data/schema'; router.post('/graphql', graphqlKoa({schema: schema})); router.get('/graphql', graphqlKoa({schema: schema}));
В папке src создайте папку data . В папке data создайте файл schema.js и добавьте папку user в которой нам потребуются 3 файла: queries.js , mutations.js и models.js .
Вся схема взаимосвязи будет выглядеть следующим образом:

Прежде чем углубляться, давайте разберемся. У Jane Dohe один нюанс: ей нужно объяснить, где можно взять сахар и молоко. Так вот, когда нам потребуется получить с сервера данные, добавить, изменить, удалить, то каждый случай необходимо описать отдельно.
Например, для получения данных пользователя, мы создадим отдельное поле User, которое по определенным критериям найдет и вернет одного пользователя. То же самое для массива пользователей Users. Любые операции для вывода данных в GraphQL называются — queries и будут храниться в queries.js .
Аналогично queries, операция добавление, удаление и изменение данных, называются mutations и будут храниться в mutations.js . Каждой операции будет соответствовать конкретное поле: UserCreate, UserDelete, UserEdit.
Queries и mutations имеют много общего, помимо того, что они практически идентичны — у них общая модель.
models.js — это файл в котором мы описываем схему коллекции данных, определяем имя, описываем типы, отдельно для queries и mutations.
Типы очень похожи на схему коллекции, при этом имеет три явных преимущества:
- Типы фильтруют входящие запросы. Вы можете их считать дополнительной защитой на пути к базе данных.
- Из-за того, что запросы проверяются до модели, это увеличивает производительность сервера.
- В типах можно ограничивать исходящие данные. Например, запретить получение пароля пользователя или другую важную информацию. Для этого достаточно их не указывать.
Именно из-за преимуществ, для queries и mutations будут отдельные типы.
GraphQL — Just do it!
Пришло время заполнить последние файлы с кодом.
Установите модуль для работы GraphQL сервера, который включает уже готовые пакеты для создания схемы, мутаций, запросов:
npm i -S graphql
Схема — это ядро GraphQL сервера. Она может быть только одна и содержать только по 1 параметру queries и mutations.
Добавим код в schema.js :
import { GraphQLObjectType, GraphQLSchema } from 'graphql'; // импортируем queries и mutations из папки user import UserQueries from './user/queries' import UserMutations from './user/mutations' // создадим GraphQL схему и заполним параметрами // каждый параметр может содержать только один GraphQLObjectType export default new GraphQLSchema({ query: new GraphQLObjectType({ name: 'Query', // произвольное имя для API библитеки fields: UserQueries // поля из файла queries.js }), mutation: new GraphQLObjectType({ name: 'Mutation', fields: UserMutations }) });
От схемы перейдем к models.js :
import { GraphQLObjectType, GraphQLInputObjectType, GraphQLNonNull, GraphQLString, GraphQLID } from 'graphql'; import mongoose from 'mongoose'; // схема коллекции const schema = new mongoose.Schema({ firstName: { type: String, }, lastName: { type: String, } }); // определяем коллекцию User и подключаем к ней схему export let UserModel = mongoose.model('User', schema); // тип для queries export let UserType = new GraphQLObjectType({ name: 'User', fields: { _id: { type: new GraphQLNonNull(GraphQLID) }, firstName: { type: GraphQLString }, lastName: { type: GraphQLString } } }); // тип для mutations export let UserInput = new GraphQLInputObjectType({ name: "UserInput", fields: { firstName: { type: GraphQLString }, lastName: { type: GraphQLString } } });
Вспомните, мы ранее говорили о полях User и Users, для вывода пользователя и пользователей соответственно. Пора заполнить файл queries.js :
import { GraphQLID, GraphQLList, GraphQLNonNull } from 'graphql'; // импортируем данные из models.js import {UserModel, UserType, UserInput} from './models'; // создаем поле для получения одного пользователя const User = { type: UserType, // тип для получения данных пользователя args: { // аргумент для поиска пользователь id: { name: 'id', type: new GraphQLNonNull(GraphQLID) } }, // метод, в котором формируется запрос и возвращаются данные resolve (root, params, options) { return UserModel .findById(params.id) .exec(); // возвращаем JSON } }; const Users = { type: new GraphQLList(UserType), args: {}, resolve (root, params, options) { return UserModel .find() .exec(); } }; export default { User: User, Users: Users, }
Mutations практически аналогичны queries. Queries выполняются асинхронно, а mutations последовательно, один за одним. Добавьте код в mutations.js .
import { GraphQLNonNull, GraphQLBoolean, } from 'graphql'; import {UserModel, UserType, UserInput} from './models'; const UserCreate = { description: "Create new user", type: GraphQLBoolean, args: { data: { name: "data", type: new GraphQLNonNull(UserInput) } }, async resolve (root, params, options) { const userModel = new UserModel(params.data); const newUser = await userModel.save(); if (!newUser) { throw new Error('Error adding new user'); } return true; } }; export default { UserCreate: UserCreate, }
Я вас поздравляю! Вы создали свой GraphQL сервер с нуля. Осталось его протестировать.
npm run dev
Если в консоле ошибки, то обратитесь к рабочему репозиторию Github. При запущеном, рабочем сервере, перейдите по ссылке в браузере:
http://localhost:3000/graphiql
В открытом окне, напишите свои первые мутации:
mutation firstMutation{ UserCreate(data: {firstName: "John", lastName: "Dohe"}) } mutation secondMutation{ UserCreate(data: {firstName: "Jane", lastName: "Dohe"}) }
При успешном результате вы получите:
{ "data": { "UserCreate": true } }
Последним шагом, выведем всех пользователей из MongoDB:
{ Users{ firstName lastName } }
В ответ мы получим:
{ "data": { "Users": [ { "firstName": "John", "lastName": "Dohe" }, { "firstName": "Jane", "lastName": "Dohe" } ] } }
На этом мы закончили. Возможно, к этой статье вы пришли с базовыми знаниями или нашли для себя что-то новое. Так, начиная с простых вещей о node.js, создания сервера на Koa и подключением к MongoDB, полулось собрать полностью рабочий GraphQL сервер.
Если у вас имеются вопросы или пожелания, я с удовольствием отвечу в комментариях.
Спасибо всем за внимание.
ссылка на оригинал статьи https://habrahabr.ru/post/327816/
Добавить комментарий