Тарифы Услуги Сим-карты

Основы Node JS & Express (III). Создание HTML-формы и получение данных. Обновление заметок: маршрут UPDATE

Express представляет собой популярный веб-фреймворк, написанный на JavaScript и работающий внутри среды исполнения node.js. Этот модуль освещает некоторые ключевые преимущества этого фреймворка, установку среды разработки и выполнение основных задач веб-разработки и развертывания.

Предварительные требования

Перед началом этого модуля вам необходимо представлять, что из себя представляет серверное программирование и веб-фреймворки, желательно из прочтения статей другого модуля Server-side website programming first steps . Знакомство с основными концепциями программирования и языком программирования JavaScript будет очень полезным, но оно не является обязательным для понимания базовых понятий этого модуля.

Заметка : Этот веб-сайт содержит множество источников для изучения JavaScript в контексте разработки на стороне клиента : JavaScript , JavaScript Guide , JavaScript Basics , JavaScript (изучение). Ключевые особенности и коцепции языка JavaScript остаются сходными и для серверной разработки на Node.js и используемый материал достаточно релевантен. Node.js предоставляет additional APIs для обеспечения функционала, который полезен для "безбраузерной" разработки, т.е. для создания HTTP-сервера и доступа к файловой системе, но не поддерживает JavaScript APIs для работы с браузером и DOM.

Это руководство обеспечит вас некоторой информацией о работе с Node.js и Express, но также существуют и другие многочисленные отличные ресурсы в Интренете и книгах - некоторые из них доступны из тем How do I get started with Node.js (StackOverflow) и (Quora).

Руководства

Введение в Express/Node В первой статье об Express мы ответим на вопросы "Что такое Node?" и "Что такое Express?" и дадим вам представление о том, что делает веб-фреймворк Express особенным. Мы расскажем об основных функциях и покажем вам некоторые из основных строительных блоков приложений Express (хотя на данный момент у вас еще нет среды разработки, в которой можно ее протестировать) . Настройка среды разработки Node (Express)

Теперь, когда вы знаете, что такое Express, мы покажем вам, как настроить и протестировать среду разработки Node/Express в Windows, Linux (Ubuntu) и Mac OS X. Независимо от того, какую популярную операционную систему вы используете, эта статья даст вам то, что вам нужно, чтобы начать разработку приложений Express.

Учебник Express: сайт LocalLibrary

Первая статья в нашей серии практических уроков объясняет, что вы будете изучать, и предоставит обзор веб-сайта «локальной библиотеки», над которым мы будем работать и развивать в последующих статьях.

Учебник Express часть 2: Создание скелета веб-сайта

В этой статье показано, как вы можете создать «скелет» веб-сайта, который затем можно будет заполнить с помощью маршрутов сайта, шаблонов/представлений и баз данных.

Учебник Express часть 3: Использование базы данных (с помощью Mongoose) В этой статье кратко представлены базы данных для Node/Express. Затем показывается, как мы можем использовать Mongoose для обеспечения доступа к баз данных для сайта LocalLibrary . В уроке объясняется, как объявляются объектная схема и модели, основные типы полей и базовая валидация. Также кратко показаны некоторые из основных способов доступа к данным модели. Учебник Express часть 4: Маршруты и контроллеры В этом уроке мы создадим маршруты (код обработки URL) с "фиктивным" обработчиком функций для всех конечных точек ресурсов, которые нам в конечном итоге понадобятся для сайта LocalLibrary . По завершении мы будем иметь модульную структуру нашего кода обработки маршрута, который мы можем расширить с помощью функций реального обработчика в следующих статьях. Мы также будем очень хорошо понимать, как создавать модульные маршруты, используя Express. Учебник Express часть 5: Отображение данных библиотеки Теперь мы готовы добавить страницы, на которых будут отображаться книги веб-сайта LocalLibrary и другие данные. Страницы будут включать главную страницу, которая показывает сколько записей определенного типа мы имеем и отдельную страницу для детального просмотра записи. По пути мы получим практический опыт в получении записей из баз данных и использовании шаблонов. Учебник Express часть 6: Работы с формами В этой части мы покажем вам, как работать с HTML формами в Express, используя Pug, и в частности, как создавать, обновлять и удалять документы из базы данных. Учебник Express часть 7: Выкладка в production Теперь когда вы создали восхитительный сайт LocalLibrary , вы захотите установить его на общедоступном сервере, чтобы он мог дать доступ персоналу библиотеки и пользователям в Интернет. В этой статье представлен обзор того, как вы можете найти хост для развертывания вашего сайта и что вам нужно сделать, чтобы подготовить ваш сайт к публикации. Установка LocalLibrary на PWS/Cloud Foundry В этой статье представлена практическая демонстрация того, как установить LocalLibrary на облаке Pivotal Web Services PaaS - это полнофункциональная альтернатива с открытым исходным кодом для Heroku, облачного сервиса PaaS используемого в части 7 этого учебника, представленного выше. PWS/Cloud Foundry опредленно стоит попробовать, если вы ищете альтернативу Heroku (или другому PaaS облачному сервису), или просто хотите попробовать что-то другое.

Эта статья предназначена для начинающих разработчиков и всех, кто заинтересован в работе с Node js Express . Для освоения вы должны знать основы JavaScript :

Что такое Node.js?

Node.js — это асинхронная среда выполнения JavaScript , основанная на движке JavaScript V8 от Chrome . Она предназначена для создания масштабируемых сетевых приложений.

Node.js позволяет писать JavaScript-код на стороне сервера. Теперь вы можете задуматься, каким образом? JavaScript — это язык, который работает в браузере. Браузер принимает код JavaScript и компилирует его в команды. Создатель Node.js взял движок Chrome и построил среду выполнения (runtime ), чтобы он работал на сервере. Это среда, в которой язык может интерпретироваться. Итак, что у нас есть сейчас? Способ записи JavaScript в бэкэнде.

Что касается определения, вам может быть интересно, что означает термин «асинхронный » в данном контексте. JavaScript однопоточный язык. Поэтому вы не хотите, чтобы события прерывали основной поток выполнения. Это означает обработку событий без прерывания основного потока.

Node.js основан на этом неблокирующем исполнении, что делает его одним из самых быстрых инструментов для создания веб-приложений. В следующем примере «Hello World » многие соединения могут обрабатываться одновременно. При каждом соединении запускается обратный вызов.

В этом Node js Express примере есть шесть простых шагов.

  1. Установите Node.js для своей платформы (MacOS, Windows или Linux )

Node.js

Node.js® — это среда выполнения JavaScript , встроенная в механизм JavaScript V8 для Chrome . Node.js использует управляемые события, неблокирующий ввод-вывод…

Первый шаг состоит в том, чтобы получить экземпляр JavaScript на вашем локальном компьютере. Вбейте nodejs.org в адресной строке браузера или кликните по ссылке , и готово. Стартовое окно должно сразу дать вам то, что вы хотите. Когда я запускаю на своем компьютере Ubuntu , отображается соответствующая версия Node.js для моей операционной системы. Загрузите и установите его. Это предоставим вам инструменты, необходимые для запуска сервера на локальном компьютере:


  1. Откройте командную строку и введите

mkdir myapp cd myapp

Эти команды Node js Express Post универсальны для любой операционной системы. Первая создаст новый каталог внутри каталога, в котором вы сейчас находитесь, mkdir = «make directory» . Последний изменится на этот вновь созданный каталог, cd = «change directory» .

  1. Запустите свой проект и привяжите его к npm

После создания каталога с именем myapp нужно будет запустить проект и связать его с npm .

Npm является сокращением от node package manager (диспетчер пакетов Node ). Это то место, где находятся все пакеты Node . Их можно рассматривать как пакеты кода, модули, которые выполняют определенную функцию. Мы используем интерфейс прикладных программ, API , предоставляемый этими модулями.

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

Она создает файл package.json в папке myapp . Файл содержит ссылки на все пакеты npm, которые загружены в проект.

Команда предложит вам ввести несколько вариантов действий. Можно ввести свой путь через все из них за исключением этого:

entry point: (index.js)

Вы захотите изменить это на:

  1. Установите Express в каталог myapp

Express — это минимальная и гибкая инфраструктура веб-приложений Node.js , которая обеспечивает надежный набор функций для интернета.

Находясь в каталоге myapp , запустите:

npm install express --save

Команда установки продолжит поиск пакета Node js Express files , который необходимо установить. Установите его в свой проект.

Теперь папка node_modules создается в корне вашего проекта. Добавление -save позволяет сохранять пакет в список зависимостей, расположенный в package.json , в каталоге myapp .

Express предоставляет набор инструментов для создания и запуска веб-приложения. Express стал настолько популярен, что теперь он является стандартом в подавляющем большинстве приложений Node.js . Я настоятельно рекомендую использовать Express .

  1. Запустите текстовый редактор и создайте файл с именем app.js

После установки Express Node добавьте в созданный файл, приведенный ниже код:

var express = require("express"); var app = express(); app.get("/", function (req, res) { res.send("Hello World!"); }); app.listen(3000, function () { console.log("Example app listening on port 3000!"); });

Здесь нужно будет использовать пакет, который был недавно установлен. Первая строка объявляет переменную, которая будет содержать модуль express, находящийся в папке node_modules .

Модуль является функцией. Назначение вызова функции другой переменной обеспечивает доступ к предопределенному набору инструментов, которые облегчают дальнейшую работу. Можно рассмотреть временное приложение как объект, методы которого вы используете для создания реальной программы.

Метод прослушивания запускает сервер и прослушивает порт 3000 для соединений. Он отвечает «Hello World! » для запросов GET к корневому URL (/) . Для любого другого пути он ответит 404 Not Found .

  1. Запустите приложение

Введите команду:

После выполнения команды введите в браузере http: // localhost: 3000 / , чтобы увидеть результат. Вы также должны увидеть «Example app listening on port 3000 »:


Вот все и готово. Вы успешно создали свое первое приложение Node.js Express . Не останавливайтесь на этом, продолжайте изучать чудесный мир Node.js , так как он предлагает гораздо больше возможностей.

В мы рассмотрели, что из себя представляет архитектура REST, шесть основных требований, которые выдвигаются к REST, значение методов запроса HTTP и кодов состояния ответов и структуру конечной точки RESTful API .

В этом руководстве мы создадим сервер, на котором будет располагаться наш API. Вы можете создавать API при помощи любого языка программирования и любого серверного программного обеспечения, однако мы будем использовать платформу Node.js , которая является реализацией JavaScript для стороны сервера, и Express – популярный фреймворк для Node.js с самым необходимым функционалом.

Установка

Для начала нам необходимо убедиться, что Node.js и npm установлены глобально на нашем компьютере. Мы можем это проверить при помощи выполнения команды с флажком -v , в результате чего будут показаны установленные версии этих инструментов. Откройте вашу консоль и введите туда следующую команду:

Node -v && npm -v v10.8.0 6.2.0

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

Давайте создадим папку проекта под названием express-api и перейдем в нее.

Mkdir express-api && cd express-api

Теперь, когда мы в ней, мы можем инициализировать наш проект, выполнив команду init.

Npm init

В результате вам будет предложен ряд вопросов о проекте, на которые вы можете как отвечать, так и нет. После настройки у вас будет файл package.json , который выглядит следующим образом:

{ "name": "express-api", "version": "1.0.0", "description": "Node.js and Express REST API", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "Tania Rascia", "license": "MIT" }

Теперь, когда у нас есть package.json , мы можем установить зависимости, необходимые для нашего проекта. К счастью, нам нужны только следующие:

  • body-parser – промежуточное ПО для разбора тела запросов;
  • express – веб-фреймворк с самым необходимым функционалом, который мы будем использовать для создания нашего сервера;
  • mysql : драйвер MySQL;
  • request (необязателен) – легкий способ выполнения запросов HTTP;

Мы воспользуемся командой install , за которой будут следовать все зависимости, для завершения настройки нашего проекта.

Npm install body-parser express mysql request

В результате будут созданы файл package-lock.json , папка node_modules , и package.json теперь будет выглядеть подобно следующему:

{ "name": "express-api", "version": "1.0.0", "description": "Node.js and Express REST API", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "Tania Rascia", "license": "MIT", "dependencies": { "dependencies": { "body-parser": "^1.18.3", "express": "^4.16.3", "mysql": "^2.16.0", "request": "^2.88.0" } }

Создание сервера HTTP

Перед тем как создать сервер Express, мы быстренько создадим сервер HTTP при помощи встроенного модуля http Node, чтобы вы получили общее представление о том, как работает простенький сервер.

Создайте файл под названием hello-server.js . Загрузите модуль http , установите значение порта (я выбрала 3001) и создайте сервер при помощи метода createServer() .

// Build a server with Node"s HTTP module const http = require("http"); const port = 3001; const server = http.createServer();

Во вступительном руководстве этой серии мы рассмотрели, какую роль выполняют запросы и ответы для сервера HTTP. Мы настроим наш сервер так, чтобы он мог обрабатывать запрос и отображать его URL-адрес на стороне сервера, а также так, чтобы на стороне клиента отображалось сообщение «Hello, server! ».

Server**on("request"** (request, response) => { console.log(`URL: ${request.url}`); response.end("Hello, server!") })

Наконец, мы укажем серверу, какой порт прослушивать и будем выводить ошибки при их наличии.

// Start the server server.listen(port, (error) => { if (error) return console.log(`Error: ${error}`); console.log(`Server is listening on port ${port}`) })

Теперь мы можем запустить наш сервер при помощи команды node , за которой следует имя файла.

Node hello-server.js

Вы увидите ответ в консоли.

Server is listening on port 3001

Для того чтобы проверить, действительно ли запустился сервер, перейдите в вашем браузере по адресу http://localhost:3001/ . Если все нормально, то вы увидите «Hello, server! » на странице. В вашей консоли вы увидите запрошенный URL-адрес.

URL: / URL: /favicon.ico

Если бы вы перешли по адресу http://localhost:3001/hello , то увидели бы URL: /hello .

Также мы можем использовать инструмент cURL на нашем локальном сервере, за счет чего нам будут показаны точные возвращенные заголовки и тело ответа.

Curl -i http://localhost:3001 HTTP/1.1 200 OK Date: Wed, 15 Aug 2018 22:14:23 GMT Connection: keep-alive Content-Length: 14 Hello, server!

Если вы закроете консоль, когда захотите, то сервер прекратит работу.

Теперь, когда мы получили общее представление о том, как работает сервер, запрос и ответ вместе, мы можем переписать этот код для Express, интерфейс которого даже проще и возможности которого более широки.

Создаем сервер Express

Мы создадим новый файл, app.js , который будет выступать в роли точки входа (* файл для запуска приложения) для собственно нашего проекта. Так же как и в случае с оригинальным сервером http, мы запросим модуль и укажем порт для запуска сервера.

Создайте файл app.js и добавьте туда следующий код:

// Require packages and set the port const express = require("express"); const port = 3002; const app = express();

Теперь, вместо того чтобы прослушивать все запросы, мы явно укажем серверу, что нам необходимы только запросы, выполненные по методу GET к корневой папке сервера (/). При получении конечной точкой запроса « / » мы отобразим запрошенный URL-адрес и выведем сообщение «Hello, Server!».

App.get("/", (request, response) => { console.log(`URL: ${request.url}`); response.send("Hello, Server!"); });

Наконец, мы запустим сервер, который будет прослушивать запросы, выполненные по 3002 порту, при помощи метода listen() .

// Start the server const server = app.listen(port, (error) =>

Мы можем запустить сервер при помощи команды node app.js , как и ранее, однако мы можем изменить свойство scripts в файле package.json для автоматического запуска этой конкретной команды.

"scripts": { "start": "node app.js" },

Теперь мы можем использовать команду npm start для запуска сервера, и после запуска мы увидим сообщение в консоли.

Server listening on port 3002

Если мы выполним команду curl -i для обсуждаемого URL-адреса, то увидим, что сервер в этом случае работает на базе Express и что имеются некоторые дополнительные заголовки вроде Content-Type .

Curl -i http://localhost:3002 HTTP/1.1 200 OK X-Powered-By: Express Content-Type: text/html; charset=utf-8 Content-Length: 14 ETag: W/"e-gaHDsc0MZK+LfDiTM4ruVL4pUqI" Date: Wed, 15 Aug 2018 22:38:45 GMT Connection: keep-alive Hello, Server!

Добавляем промежуточное ПО для разбора тела запросов

Для того чтобы облегчить работу с запросами по методам POST и PUT к нашему API, мы добавим промежуточное ПО для разбора тела запроса. Тут нам и пригождается модуль body-parser . За счет этого модуля будет извлечено все тело пришедшего запроса, а его данные преобразованы в JSON-объект, с которым мы можем работать.

Мы просто запросим модуль вверху кода нашего файла. Добавьте следующую инструкцию require в верхнюю часть вашего файла app.js .

Const bodyParser = require("body-parser"); ...

Затем мы укажем нашему приложению Express, что необходимо использовать body-parser и преобразовывать данные в формат JSON.

// Use Node.js body parsing middleware app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true, }));

Также давайте изменим наше сообщение таким образом, чтобы вместо простого текста в качестве ответа отправлялся JSON-объект.

Response.send({message: "Node.js and Express REST API"});

// Require packages and set the port const express = require("express"); const port = 3002; const bodyParser = require("body-parser"); const app = express(); // Use Node.js body parsing middleware app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true, })); app.get("/", (request, response) => { response.send({ message: "Node.js and Express REST API"}); }); // Start the server const server = app.listen(port, (error) => { if (error) return console.log(`Error: ${error}`); console.log(`Server listening on port ${server.address().port}`); });

Если вы отправите запрос при помощи curl -i на сервер, то увидите, что в заголовке Content-Type теперь указано значение application/json; charset=utf-8 .

Настраиваем маршруты

Пока что у нас имеется только маршрут для обработки запросов по методу GET к корню приложения « / »), однако наш API также должен быть способен обрабатывать запросы HTTP по всем главным методам к различным URL. Мы настроим маршрутизатор (* предоставляет функциональные возможности для обработки ответов) и добавим некоторые выдуманные данные для отправления пользователю.

Давайте создадим новую папку под названием routes и файл под названием routes.js . Мы подключим его вверху app.js .

Const routes = require("./routes/routes");

Обратите внимание на то, что расширение.js в require указывать необязательно. Теперь мы переместим маршрут для обработки запросов GET в routes.js . Добавьте следующий код в routes.js :

Const router = app => { app.get("/", (request, response) => { response.send({ message: "Node.js and Express REST API" }); }); }

Наконец, экспортируйте маршрутизатор, чтобы мы могли им воспользоваться в нашем файле app.js

// Export the router module.exports = router;

В app.js замените имеющийся код app.get() вызовом routes() :

Routes(app);

Теперь вы могли бы перейти по http://localhost:3002 и увидеть то же, что и ранее. (Не забудьте перезапустить сервер!)

После удачной настройки вышеуказанного мы предоставим некоторые данные в формате JSON при помощи другого маршрута. Пока что мы воспользуемся просто выдуманными данными, поскольку наша база данных еще не создана.

Давайте создадим переменную users в routes.js с некоторыми выдуманными пользовательскими данными в формате JSON.

Const users = [{ id: 1, name: "Richard Hendricks", email: "[email protected]", }, { id: 2, name: "Bertram Gilfoyle", email: "[email protected]", }, ];

Мы добавим еще один маршрут для обработки запросов по адресу /users и методу GET в наш маршрутизатор и будем отправлять с его помощью пользовательские данные.

App.get("/users", (request, response) => { response.send(users); });

После перезапуска сервера теперь вы можете перейти по http://localhost:3002/users и увидеть все наши данные.

Обратите внимание: если у вас не установлено в браузере расширения для просмотра файлов в формат JSON, то я вам очень рекомендую скачать его, например JSONView для Chrome. Благодаря этому вам будет намного проще читать данные!

Посетите репозиторий GitHub , чтобы ознакомиться с конечным кодом для этого поста и сравните его со своим.

Заключение

В этом руководстве мы рассмотрели, как создать сервер при помощи встроенного модуля Node HTTP и при помощи Express, как назначить маршруты для запросов, выполняемых по различным URL-адресам, и как получать пришедшие в запросах по методу GET данные в формате JSON.

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

В серии статей мы разберем основы создания web-сервиса на Node.js и Express.js, продемонстрируем взаимодействие с базами данных MySQL, MongoDB и Redis, покажем, как организовать авторизацию пользователей на web-сервисе c помощью логина и пароля, а также аккаунта в социальной сети с использованием модуля Passport, расскажем, как разграничить доступ к различным ресурсам web-сервиса с помощью ролей (Access Control List), а также сделаем сервис отказоустойчивым и масштабируемым.

Бандинги (Bindings) - служат связующей прослойкой между кодом, написанным на С/С++, и кодом, написанным на Javascript.

Вместо традиционной для серверов многопоточной модели - на каждое подключение выделяется один поток - Node все подключения обрабатывает в одном потоке. Этот поток называется циклом событий (именно в нем исполняется проинтерпретированный пользовательский javascript код приложения). Когда поступает запрос ввода/вывода (действие, емкое с точки зрения времени), цикл событий назначает эту задачу либо операционной системе, когда дело касается работы с сетью, либо контроллеру пула потоков, когда требуется работа с файловой системой или dns (по умолчанию используется 4 потока). Затем регулярно опрашивает о состоянии операции и по ее завершении выполняет заранее назначенное действие (запускается callback-функция или срабатывает прослушиватель событий - в этом заключается событийная ориентированность Node). Возникающие события выстраиваются в специальную очередь (Event Queue), которая определяет порядок обработки событий циклом событий. Поскольку цикл событий не ждет результата операции ввода/вывода, очередной запрос не блокируется на время выполнения операции ввода/вывода, а сама операция выполняется асинхронно по отношению к циклу событий. «Из коробки» Node не поддерживает асинхронное выполнение операций, требующих ресурсов CPU, и такие задачи блокируют цикл событий. Обойти эту проблему позволяют сторонние модули (например, webworker-threads).

Прежде, чем устанавливать nvm, желательно удалить Node.js и npm. Как это сделать описано и . Также в системе должен быть установлен C++ компилятор. Для OS X достаточно установить консольную утилиту Xcode:

Xcode-select --install

Далее удостоверьтесь, что файл ~/.bash_profile существует, иначе создайте его командой touch ~/.bash_profile . Теперь все готово для установки nvm (замените версию ниже на последнюю):

Curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.4/install.sh | bash

В рамках данной статьи из всех возможностей утилиты nvm мы воспользуемся только установкой последней версии Node.

Принцип нумерации версий Node.js. Стоит пояснить принцип нумерации версий Node. Каждая новая версия (v.5, v.6, …) выходит раз в полгода. Четные версии (выходят в апреле) фокусируются на стабильности и безопасности и имеют длительный период поддержки - Long Term Support plan (18 месяцев активной поддержки и год обычной). Этот статус очередная четная версия приобретает во время выхода новой нечетной версии. С обновлениями LTS версии уже не наделяются новым функционалом, а получают только исправление багов, влияющих на стабильность, обновление безопасности, некритические улучшения производительности и пополнение документации. Четные версии подходят для компаний со сложной организацией кода, для которых частое обновление обременительно. Напротив, нечетные версии (выходят в октябре) получают обновления часто. С обновлениями активно нарабатывается новый функционал, улучшаются существующие API и производительность. Такие версии поддерживаются не более восьми месяцев и носят больше характер экспериментальной площадки.

На момент написания статьи последней версией была v.6.3.1. Шестая версия получила существенные улучшения производительности, надежности, удобства работы и безопасности. Хотя v.6 пока еще не достигла LTS статуса, работать мы будет именно с ней. Для установки последней версии выполните в терминале

Nvm install node

И проверим установку

Node -v v.6.3.1

Если все правильно установилось, эта команда должна вывести версию Node.js.

Построение приложений на Node.js основано на модульном подходе. В силу популярности Node, большим сообществом приверженцев создано огромное количество модулей, значительно расширяющих функционал. Для установки модулей предназначен пакетный менеджер npm, который поставляется вместе с Node.js. Проверим версию менеджера.

Npm -v 3.10.3

Помимо установки модулей, npm следит за их версиями - два модуля могут быть зависимы от третьего, но использовать разные его версии. Раньше менеджер npm помещал зависимый модуль в папку модуля, который его использует. Получалась вложенная структура и зачастую в разных папках хранились одинаковые модули с одинаковыми версиями. Начиная с npm v.3, модули хранятся линейно в одной папке, и только когда возникает конфликт версий, модули помещаются вложенно.

Наш web-сервис будет создаваться на основе модуля Express.js - самого популярного web фреймворка для Node.js. Node не накладывает строгих ограничений на организацию кода, предоставляя разработчикам свободу выбора. Мы будем использовать шаблон mvc. Для генерации mvc-каркаса приложения воспользуемся пакетом express-generator , для этого в терминале выполним команду.

Npm install -g express-generator

В результате пакетный менеджер npm установит модуль express-generator . Флаг -g означает глобальную установку, т.е. запускать этот модуль в терминале мы можем из-под любого пути. Заметьте, что если бы для установки Node мы не использовали nvm, то при глобальной установке модулей приходилось бы прибегать к использованию sudo , что не является безопасным. Далее создадим mvc-каркас командой

Express ~/Documents/site/app

Директория ~/Documents/site/app будет корневой для нашего проекта (все относительные пути в статье будут вестись от корневой директории). Перейдем в созданную директорию и установим зависимости, прописанные в файле./package.json (модули устанавливаются в./node_modules)

Cd ~/Documents/site/app && npm install

И запустим приложение

Npm start

При этом npm выполнит команду, прописанную в./package.json

{ ... "scripts": { "start": "node ./bin/www" }, ... }

Теперь переходите по адресу http://localhost:3000 . Если отобразилась приветственная надпись «Welcome to Express», то поздравляем - все готово для следующего шага!

Базы данных

Наш сервис для хранения пользователей, продуктов, предзаказов и системы прав доступа будет использовать MySQL, для сессий - Redis, а для отправленных смс-кодов - MongoDB.

MySQL

Эта реляционная СУБД в представлении не нуждается. Скачаем DMG образ MySQL сервера и запустим установку. В конце установки появится диалоговое окно, сообщающее временный пароль пользователя root.

Изменим временный пароль

/usr/local/mysql/bin/mysqladmin -u root -p password Enter password: New password: Confirm new password: Warning: Since password will be sent to server in plain text, use ssl connection to ensure password safety.

Запускается и останавливается сервер через панель MySQL в системных настройках.

Работать со схемой базы данных будем в MySQL Workbench .

Redis и MongoDB

Redis является сетевым журналируемым хранилищем данных типа «ключ - значение», относится к нереляционным СУБД высокой производительности, поскольку хранит базу данных в оперативной памяти. MongoDB - нереляционная СУБД для хранения JSON объектов.

Как Redis, так и MongoDB удобно устанавливать через Homebrew - пакетный менеджер для Mac OS X. Обновим базу пакетов менеджера и установим Redis командой

Brew update && brew install redis

Запустим как сервис

Brew services start redis

MongoDB устанавливается командой

Brew install mongodb

Создадим директорию

Mkdir ~/Documents/site/data

И запустим MongoDB по этому пути

Mongod --dbpath ~/Documents/site/data

Для проверки наберите в другом окне терминала

Должно появиться следующее:

На скриншоте сервер выдал предостережение, которое можно просто проигнорировать, если ваш проект в стадии разработки. Иначе можете посмотреть .

Файл конфигурации приложения

Создадим в корне проекта две вложенные директории и пустой файл

Mkdir -p config/development && touch ./config/development/index.js

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

// файл./config/development/index.js var config = { db: { mysql: { host: "localhost", user: "root", database: "appdb", // можете заменить "appdb" на свое название password: "yourPasswordHere" // замените это на root пароль }, // от MySQL Server mongo: "mongodb://localhost/ourProject" // можете заменить "ourProject" }, // на свое название redis: { port: 6379, host: "127.0.0.1" }, port: 3000 }; module.exports = config;

Подключим этот файл к./bin/www следующим образом

// файл./bin/www //... var config = require("../config/" + (process.env.NODE_ENV || "development")); //... //var port = normalizePort(process.env.PORT || "3000"); var port = normalizePort(process.env.PORT || config.port); //...

Это позволит нам подключать разные файлы конфигурации в зависимости от параметров запуска приложения. Например, если мы создадим конфигурационный файл./config/production/index.js , то чтобы он применился, приложение следует запускать так

NODE_ENV=production npm start

Несколько слов о require, module.exports и exports

Node.js исповедует модульный подход построения приложений, причем в качестве модуля всегда выступает отдельный файл (*.js , *.json , *.node , либо файл с javascript кодом без расширения). За подключение модулей отвечает функция require . Если модуль встроенный или находится в./node-modules (или в../node-modules и выше), то в качестве параметра функции require указывается только название модуля, например require("http") . Иначе функции require передается путь (т.е. строка, начинающаяся с "./" или "/" , или "../"), например такой "./libs/dbs.js" . Расширение модуля можно не указывать и просто писать "./libs/dbs" . В таком случае, если dbs не окажется файлом модуля, dbs воспринимается как директория, и в ней ищется файл модуля с именем index . Так мы поступили выше при подключении файла конфигурации к./bin/www . Весь алгоритм получения пути к модулю по строке описывается .

Переменная, объявленная в модуле обычным образом, не будет доступна через require - ее надо передать через module.exports или exports (является ссылкой на module.exports и используется для более короткой записи). Пример ниже поясняет ситуацию

// файл module.js var a = ; var b = ; exports.a = a; // файл uses_module.js var module = require("./module"); console.log(module.a) // console.log(module.b) // undefined

Таким образом можно передавать любые переменные, включая функции и конструкторы. Переменную можно напрямую присваивать объекту module.exports (но не exports , поскольку это только ссылка), как мы и сделали с конфигурационным файлом выше.

При первом подключении модуля функция require кэширует его и помещает в объект require.cache . При последующих подключениях того же модуля объект грузится из кэша. Такая модель реализует шаблон Singleton.

Подключение баз данных к Node.js

Установка драйверов

Для MySQL мы не будем использовать ORM - вся нагрузка ляжет на хранимые процедуры, которые будут вызываться из репозиториев соответствующих объектов. Стандартным драйвером для работы с MySQL в Node является npm модуль mysql (есть более быстрый драйвер mysql2, но он пока находится на стадии релиз-кандидата). При написании кода мы будем придерживаться стиля с использованием промисов, и поскольку модуль mysql не поддерживает такой стиль, воспользуемся модулем-оберткой mysql-promise. Перейдем к корневой директории проекта и установим его

Cd ~/Documents/site/app && npm install mysql-promise --save

Флаг --save указывает пакетному менеджеру на сохранение зависимости в файл package.json . С драйвером для Redis дела обстоят похожим образом - воспользуемся модулем-оберткой promise-redis вокруг стандартного драйвера redis.

Npm install promise-redis --save

И, наконец, установим Mongoose - ODM (Object-Document Mapper) для MongoDB

Npm install mongoose --save

Mongoose имеет собственную встроенную библиотеку mpromise, реализующую промисы. На данный момент эта библиотека считается устаревшей, и рекомендуется заменять ее на другую (мы заменим на стандартные ES6 промисы).

Инициализация баз данных

Создадим папку и файл в ней

Mkdir libs && touch ./libs/dbs.js

со следующим содержанием

// файл./libs/dbs.js var mysqlPromise = require("mysql-promise")(), mongoose = require("mongoose"), Redis = require("promise-redis")(), config = require("../config/" + (process.env.NODE_ENV || "development")); mysqlPromise.configure(config.db.mysql); var redis = Redis.createClient(config.redis.port, config.redis.host); mongoose.Promise = Promise; // function checkMySQLConnection(){ // return mysqlPromise.query("SELECT 1"); } function checkRedisReadyState() { // return new Promise((resolve,reject) => { redis.once("ready", () => {redis.removeAllListeners("error"); resolve()}); redis.once("error", e => reject(e)); }) } function init() { // return Promise.all([ checkMySQLConnection(), new Promise((resolve,reject) => {mongoose.connect(config.db.mongo, err => err ? reject(err):resolve())}), checkRedisReadyState() ]); } module.exports = { // mysql: mysqlPromise, redis: redis, init: init };

Опишем, что здесь происходит. Вначале подключаются драйверы баз данных и файл конфигурации. Затем конфигурируется подключение к базе MySQL, и создается клиент базы Redis. Далее по пунктам.

  1. Заменяем встроенную библиотеку промисов на стандартную ES6 библиотеку.
  2. Функция checkMySQLConnection() проверяет подключение к MySQL простым запросом. Важно отметить, что при конфигурировании подключения к MySQL создается пул подключений, и команда query вначале берет подключение из пула, выполняет запрос, затем освобождает подключение.
  3. Функция checkRedisReadyState() проверяет готовность Redis сервера.
  4. Функция init() с помощью ES6 метода Promise.all параллельно запускает проверку готовности MySQL, MongoDB и Redis. Как только одна из функций возвращает ошибку, выполнение других останавливается, и Promise.all возвращает ошибку, ловить которую будем в./bin/www методом.catch() . Если ошибка не возвращается, управление передается методу.then() .
  5. И, наконец, экспортируем переменные.

Изменим файл./bin/www

// файл./bin/www // ... // Добавим зависимости var config = require("../config/" + (process.env.NODE_ENV || "development")), dbs = require("../libs/dbs"); // ... // Заменим строчку // server.listen(port); // На следующий блок dbs.init().then(() => { console.log("Соединения с базами данных установлены успешно"); server.listen(port); }).catch(err => { console.log(err); process.exit(1); }); // ...

В результате наш не запустится, если будут проблемы с подключением к базам данных. Теперь создайте базу данных в MySQL с именем appdb и запустите наше приложение. Если все в полном порядке, в консоли мы увидим сообщение об успешном соединении с базами данных.

На этом первая часть заканчивается. В следующей части мы займемся регистрацией и ролями пользователей.

В этой главе я расскажу вам о том, как вы можете запустить простой HTTP-сервер на Node.js и начать обрабатывать запросы.

This article was translated to Russian by Andrey Melikhov, a front-end developer from Yandex.Money and editor of the collective blog about front-end, devSchacht . Find Andrey on: Twitter , GitHub , Medium & SoundCloud

Перевод этой статьи сделан Андреем Мелиховым, фронтенд-разработчиком из компании Яндекс.Деньги, редактором коллективного блога о фронтенде, devSchacht . Twitter | GitHub | Medium | SoundCloud



Модуль http для вашего Node.js-сервера

Когда вы начинаете создавать HTTP-приложения в Node.js, встроенные модули http/https - это то, с чем вы будете взаимодействовать.

Давайте создадим ваш первый HTTP-сервер на Node.js! Нам будет нужно подключить модуль http и привязать наш сервер к порту 3000 .

// содежимое index.js const http = require("http") const port = 3000 const requestHandler = (request, response) => { console.log(request.url) response.end("Hello Node.js Server!") } const server = http.createServer(requestHandler) server.listen(port, (err) => { if (err) { return console.log("something bad happened", err) } console.log(`server is listening on ${port}`) })

Затем запускаем этот скрипт:

$ node index.js

Что нужно здесь отметить:

  • requestHandler: эта функция будет вызываться каждый раз, когда на сервер придёт запрос . Если вы откроете в своём браузере адрес localhost:3000 , два сообщения появятся в консоли: одно для / и одно для favicon.ico .
  • if (err) : обработка ошибок: если порт уже занят или есть какие-то другие причины, по которым сервер не может быть запущен, мы получим уведомление об этом.

Модуль http крайне низкоуровневый: создание сложного веб-приложения с использованием вышеприведённого фрагмента кода очень трудоёмко. Именно по этой причине мы обычно выбираем фреймворки для работы над нашими проектами. Есть множество фреймворков, вот самые популярные:

В этой и следующих главах мы будем использовать Express, так как именно для него вы можете найти множество модулей в NPM.

Express

Быстрый, гибкий, минималистичный веб-фреймворк для Node.js - http://expressjs.com/

Добавление Express в ваш проект - это просто установка через NPM:

$ npm install express --save

После того, как вы установили Express, давайте посмотрим, как создать приложение аналогичное тому, что мы написали ранее:

Const express = require("express") const app = express() const port = 3000 app.get(‘/’, (request, response) => { response.send("Hello from Express!") }) app.listen(port, (err) => { if (err) { return console.log("something bad happened", err) } console.log("server is listening on ${port}") })

Самое большое различие, которое вы можете здесь заметить, заключается в том, что Express по умолчанию даёт вам роутер. Вам не нужно вручную разбирать URL, чтобы решить, что делать, вместо этого вы определяете маршрутизацию приложения с помощью app.get , app.post , app.put и так далее, а они уже транслируются в соответствующие HTTP-запросы.

Одна из самых мощных концепций, которую реализует Express - это паттерн Middleware.

Middleware - промежуточный обработчик

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

На диаграмме вы можете увидеть, как запрос идёт через условное Express-приложение. Он проходит через три промежуточных обработчика. Каждый обработчик может изменить этот запрос, а затем, основываясь на вашей бизнес-логике, третий middleware отправит ответ, либо запрос попадёт в обработчик соответствующего роута.

На практике вы можете сделать это следующим образом:

Const express = require("express") const app = express() app.use((request, response, next) => { console.log(request.headers) next() }) app.use((request, response, next) => { request.chance = Math.random() next() }) app.get("/", (request, response) => { response.json({ chance: request.chance }) }) app.listen(3000)

Что следует здесь отметить:

  • app.use: это то, как вы можете описать middleware. Этот метод принимает функцию с тремя параметрами, первый из которых является запросом, второй - ответом, а третий - коллбеком next . Вызов next сигнализирует Express о том, что он может переходить к следующему промежуточному обработчику.
  • Первый промежуточный обработчик только логирует заголовки и мгновенно вызывает следующий.
  • Второй добавляет дополнительное свойство к запросу - это одна из самых мощных функций шаблона middleware . Ваши промежуточные обработчики могут добавлять дополнительные данные к объекту запроса, который могут считывать/изменять middleware, расположенные ниже.

Обработка ошибок

Как и во всех фреймворках, правильная обработка ошибок имеет решающее значение. В Express вы должны создать специальный промежуточный обработчик - middleware с четырьмя входными параметрами:

Const express = require(‘express’) const app = express() app.get(‘/’, (request, response) => { throw new Error(‘oops’) }) app.use((err, request, response, next) => { // логирование ошибки, пока просто console.log console.log(err) response.status(500).send(‘Something broke!’) })

Что следует здесь отметить:

  • Обработчик ошибок должен быть последней функцией, добавленной с помощью app.use .
  • Обработчик ошибок принимает коллбек next . Он может использоваться для объединения нескольких обработчиков ошибок.

Рендеринг HTML

Ранее мы рассмотрели, как отправлять JSON-ответы. Пришло время узнать, как отрендерить HTML простым способом. Для этого мы собираемся использовать пакет handlebars с обёрткой express-handlebars .

Сначала создадим следующую структуру каталогов:

├── index.js └── views ├── home.hbs └── layouts └── main.hbs

После этого заполните index.js следующим кодом:

// index.js const path = require("path") const express = require("express") const exphbs = require("express-handlebars") app.engine(".hbs", exphbs({ defaultLayout: "main", extname: ".hbs", layoutsDir: path.join(__dirname, "views/layouts") })) app.set("view engine", ".hbs") app.set("views", path.join(__dirname, "views"))

Приведённый выше код инициализирует движок handlebars и устанавливает каталог шаблонов в views/layouts . Это каталог, в котором будут храниться ваши шаблоны.

После того, как вы сделали эту настройку, вы можете поместить свой начальный html в main.hbs . Чтобы всё было проще, давайте сразу перейдём к этому:

Express handlebars {{{body}}}

Вы можете заметить метку {{{body}}} - здесь будет размещён ваш контент. Давайте создадим home.hbs !

Hello {{name}}

Последнее, что мы должны сделать, чтобы заставить всё это работать, - добавить обработчик маршрута в наше приложение Express:

App.get("/", (request, response) => { response.render("home", { name: "John" }) })

Метод render принимает два параметра:

  • Первый - это имя шаблона.
  • Второй - данные, необходимые для рендеринга.

Как только вы сделаете запрос по этому адресу, вы получите что-то вроде этого:

Express handlebars

Hello John

Это всего лишь верхушка айсберга. Чтобы узнать, как добавить больше шаблонов (и даже частичных), обратитесь к официальной документации express-handlebars .

Отладка Express

В некоторых случаях вам может потребоваться выяснить, что происходит с Express, когда приложение работает. Для этого вы можете передать следующую переменную окружения в Express: DEBUG=express* .

Вы должны запустить свой Node.js HTTP-сервер, используя:

$ DEBUG=express* node index.js

Резюме

Вот как вы можете настроить свой первый HTTP-сервер на Node.js с нуля. Я рекомендую Express для начала, а затем поэкспериментируйте.

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

Gergely Nemeth

Co-founder of RisingStack

Please enable JavaScript to view the