Оглавление
Уже довольно долго в стандартный стек технологий нашей фронтенд-команды входят Node.JS, React, Redux, GraphQL и Webpack. Эта комбинация позволяет нам разрабатывать приложения, соответствующие всем современным требованиям и условиям. Ключевым же элементом стека является Node.JS. Именно о нем пойдет речь в этой статье. Но перед этим — небольшая предыстория.
Вступление
Одним из популярнейших языков программирования на сегодня является JavaScript (далее — JS). Изначальная цель создания JS заключалась в том, чтобы веб стал более динамичным. C момента релиза его первого стандарта прошел 21 год. За этот период веб-разработка поменялась чуть больше, чем полностью. JS, разумеется, не стал исключением.
За время существования JS было принято четыре стандарта. Каждый из них внес свой вклад в развитие разработки веб-приложений. Постепенно JS завоевал огромную популярность среди разработчиков и вышел за рамки целей и задач, которые перед ним ставились изначально. Сегодня этот язык программирования используется буквально повсеместно, начиная с веб-браузеров и заканчивая умными часами, телевизорами и холодильниками.
Что же сделало JS таким привлекательным? На этот вопрос каждый разработчик найдет свой ответ. Кому-то нравится синтаксис. Кому-то — возможность управлять контентом и поведением веб-страниц. Кто-то любит работать с HTML API и т.д. Все это хорошо и правильно, но мы выделим три основных момента:
- объектная ориентированность;
- асинхронное поведение;
- функциональность.
Неудивительно, что разработчикам захотелось использовать любимый JS не только для клиентской части веб-приложений, ограниченной контекстом браузера, но и получить доступ к файловой системе, бинарным данным и т.д. Такая возможность позволила бы охватить полный цикл создания приложений, не переключаясь между разными языками программирования. Она бы повысила эффективность разработки, избавив от необходимости менять окружение, типы данных, стили программирования и пр.
В 2009 году появляется Node.JS — кроссплатформенная среда выполнения JS кода на стороне сервера. В ней было реализовано все то, чего не хватало раньше. С тех пор Node.JS существенно изменился. Прежде всего отметим расширение функциональности, появление информативной API документации и пакетного менеджера npm. Изначально он насчитывал несколько десятков пакетов. Сегодня их численность возросла до 450 000, что прямо указывает на высокую популярность Node.JS. В настоящий момент эта платформа стабильно входит в топ самых распространенных серверных языков программирования.
Подобные вещи не проходят мимо гигантов IT индустрии. Крупнейшие компании используют Node.JS для разработки веб-приложений самым активным образом. Мы тоже не стали сопротивляться прогрессу и примкнули к их рядам.
Со вступлением можно заканчивать. Далее мы поделимся собственным опытом создания стартового набора для разработки серверной части приложения на основе реального проекта.
Настройка окружения
Выбор окружения для приложения напрямую зависит от типа приложения. В нашем случае это распределенное приложение, целью которого является эффективное планирование времени сотрудников компании. За клиентскую часть у нас отвечает проверенный временем React. Остается лишь настроить серверное окружение Node.JS.
Итак, первоначальные задачи: выбор архитектурного стиля, выбор фреймворка и базы данных. По первому пункту сомнений не возникло: GraphQL, являющийся языком запросов к программному интерфейсу приложения. Он прекрасно проявил себя на наших Ruby on Rails проектах.
Далее переходим к фреймворку. И тут npm предлагает богатый выбор:
- Hapi.js
- Socket.io
- Express
- Mojito
- Meteor
- Derby
- Mean.js
- Sails.js и пр.
Мы прекрасно знаем, что правильно выбранный фреймворк является основой успешной разработки и снижения рисков, которые непременно возникают при отсутствии надлежащей документации, необходимого функционала и проблем с быстродействием.
Наш выбор пал на Express. Этот фреймворк располагает, как обширной документацией и гидом для новичков и профессионалов, так и разнообразным набором инструментов для выполнения большинства поставленных задач. Если же мы что-то не найдем, в npm всегда отыщется готовое решение.
Дополнительным аргументом в пользу Express служит статистика загрузок в npm (несколько миллионов в неделю) и популярность на GitHub.
Ну и наконец — база данных. Здесь тоже никаких сомнений — PostgreSQL и Knex.JS для построения SQL запросов и Bookshelf.js для объектно-реляционного отображения данных.
Конфигурация зависимостей
Следующий шаг — установка зависимостей приложения. Как мы уже знаем, за нее в Node.JS отвечает npm. Файлом для конфигурации этих зависимостей является package.json. У нас он включает в себя такие базовые конфигурации:
Далее устанавливаем обозначенные зависимости командой:
После этого можно приступать к настройке и запуску сервера.
Компилятор Babel
Мы всегда шагаем в ногу с современными тенденциями JS и поэтому для написания приложений используем спецификацию ECMAScript 6 (ES6). Сегодня разработчики ПО со всего мира стремятся к полноценной поддержке ES6 во всех продуктах. Среди них — Node.JS. В этой связи, мы вынуждены компилировать ES6 код в стандарт ES5.
Для этого используются различные компиляторы. Самым популярным из них является Babel, позволяющий работать со всеми новинками ES6 уже сегодня.
Конфигурация плагинов и пресетов для Babel проводится в файле «.babelrc.» Наш .babelrc. Выглядит следующим образом:
Что касается пресетов, то es2015 включается в себя достаточное количество вспомогательных плагинов и отвечает за компиляцию ES6 в ES5. Пресет stage-0 включает stage-1, stage-2, stage-3 и еще несколько плагинов, реализующих поддержку фич ES6. Более детальную информацию можно найти на странице Babel.
Переменные окружения
Далее необходимо обозначить переменные окружения, в которых будет запускаться приложение. Это очень удобно, так как помогает сохранить критичные глобальные данные в одном месте и при необходимости их одномоментно заменить. Для этого прекрасно подходит модуль dotenv.
Конфигурация переменных выполняется в файле «.env». Все переменные в дальнейшем будут доступны в рамках целого проекта, как свойства объекта «process.env».
Конфигурация сервера
Теперь самое время перейти к конфигурации сервера. Для этого в основной директории мы разместили файл «app.js», являющийся основной точкой доступа к приложению.
Настало время посмотреть на результат. Для этого в файл «package.json» необходимо добавить команду, инициализирующую запуск сервера.
Здесь мы использовали модуль «nodemon», который прекрасно подходит к условиям разработки. Он запускает сервер и следит за всеми изменениями, происходящими в файлах. При необходимости — перезагружает сервер.
Итак, теперь мы в терминале выполняем «npm run dev» и открываем в браузере страницу http://localhost:4000. Вуаля!
База данных
После того как основные приготовления завершены, можно перейти к налаживанию связи с базой данных. В основной директории создаем папку «config», в которой создаем еще две папки: «migrations» и «seeds». И еще два файла: «knexfile.js» и «db.js».
Папка «migrations» содержит список миграций для нашей базы данных. Файлы-миграции создаются в результате выполнения в терминале команды knex —knexfile=config/knexfile.js migrate:make migration_name. К их названиям автоматически добавляется время создания в формате timestamp. Это необходимо для определения порядка создания миграций.
В качестве примера мы приведем две миграции для создания в базе данных таблицы ролей пользователей и самих пользователей.
Папка «seeds» содержит список сидов для наполнения базы данных. В качестве примера созданы сиды для заполнения таблицы пользователей.
Более подробную информацию про миграции, сиды и другие возможности ищите на странице Knex.js.
Knexfile.js содержит данные, необходимые для установки связи с БД.
«db.js» экспортирует экземпляр bookshelf, который в дальнейшем понадобится для работы с базой данных.
После выполнения всех действий архитектура нашего приложения выглядит следующим образом:
+— config
| +— migrations
| +— 20170116154958_roles.js
| +— 20170116154959_users.js
| +— seeds
| +— users.js
| +— db.js
| +— knexfile.js
+— .babelrc
+— .env
+— app.js
+— package.json
Далее подключаем migrations и seeds. Для этого добавляем два скрипта в «package.json»:
И выполняем их в терминале:
npm run db-migrate && npm run db-seed
Смотрим на полученный результат с помощью SQL Shell (psql) или любой другой графической оболочки:
Список таблиц
Создание моделей
Когда база данных настроена и миграции проведены, можно приступать к созданию моделей для таблиц. Для этого используем Bookshelf.js. В корне приложения создаем папку models, а в ней два файла: role.js и user.js. Именно там мы разместим наши модели.
GraphQL
Приступаем к реализации GraphQL схем. Создадим одноименную папку в корне приложения и добавим схемы:
+— config
+— graphql
| +— Role
| +— index.js
| +— mutations.js
| +— queries.js
| +— resolvers.js
| +— schema.js
| +— User
| +— index.js
| +— mutations.js
| +— queries.js
| +— resolvers.js
| +— schema.js
| +— index.js
+— models
+— .babelrc
+— .env
+— app.js
+— package.json
«index.js» объединяет и экспортирует все схемы:
Далее рассмотрим файлы, которые содержит каждая из схем.
Подстраиваем схемы под наши тестовые данные:
`
`
Добавляем вспомогательную функцию «loadModules» для сбора всех схем в единую. И размещаем эту функцию в отдельном файле в папке «utils».
+— config
+— graphql
+— models
+— utils
| +— loadModules.js
+— .babelrc
+— .env
+— app.js
+— package.json
Наконец, в конфигурационном файле сервера добавляем наши схемы в перечень импортов и express-graphql в middlewares.
Открываем страницу http://localhost:4000/graphql, на которой видим GraphiQL.
Интеграция с React
Для интеграции серверной части нашего приложения с клиентской, написанной на React, мы использовали модуль «react-apollo». Он позволяет получать данные с GraphQL сервера и использовать их для построения удобного реактивного интерфейса.
После установки react-apollo необходимо сделать кое-какие настройки. Мы приведем очень простой пример.
В файл, который отвечает за рендер клиентского приложения, следует добавить следующий импорт:
import { ApolloClient, ApolloProvider, createNetworkInterface } from ‘react-apollo’
Создаем новый образец объекта ApolloClient с определением uri-адреса, на который будут отправляться запросы.
И модифицируем выражение метода «render» следующим образом:
Здесь мы продемонстрировали лишь малую часть функционала react-apollo. Это действительно очень хороший инструмент для работы с GraphQL сервером в окружении React.
Production
Финальным этапом цикла разработки ПО является выход на рынок (production). Для этого изначальный код проходит несколько стадий обработки, компиляции и минификации. Также необходимо подготовить к выходу в продакшн серверное приложение. Для этого следует добавить дополнительные команды в package.json.
Далее в терминале выполняем команду «npm run build» и после завершения всех запрограммированных задач мы увидим скомпилированный код в папке «build». Вуаля!
Вывод
Подводя итог, можно смело сказать, что Node.JS является мощным и надежным инструментом для разработки программного обеспечения. Спектр применения Node.JS необыкновенно широк — от серверных до нативных приложений. А в связке с React и GraphQL, качество конечного продукта выходит на один уровень с ведущими игроками современного рынка ІТ.
Кстати, если вы хотите понять как работать и писать качественный SQL clause, этот туториал создан для вас!