Статьи

Создайте простое приложение для начинающих с Node, Bootstrap и MongoDB

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

Это означает, что к тому времени, как вы закончили, вы создали что-то красивое и блестящее, но у вас также есть относительно небольшое количество блюд, которые вы можете применить к своему следующему проекту.

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

Это не будет JavaScript 101. Если это то, что вы ищете, посмотрите здесь . Однако он подойдет тем людям, которые чувствуют себя достаточно уверенно с языком JavaScript и которые хотят сделать свои первые шаги в Node.js.

Что мы будем строить

Мы будем использовать Node.js и среду Express для создания простой регистрационной формы с базовой проверкой, которая сохраняет свои данные в базе данных MongoDB . Мы добавим представление в список успешной регистрации, которое мы будем защищать с помощью обычной HTTP-аутентификации, и мы будем использовать Bootstrap для добавления некоторых стилей. Учебное пособие построено так, что вы можете следовать шаг за шагом. Однако, если вы хотите выйти вперед и увидеть конечный результат, код для этого руководства также доступен на GitHub .

Основные настройки

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

Node.js

Многие веб-сайты рекомендуют вам перейти на официальную страницу загрузки Node и получить двоичные файлы Node для своей системы. Хотя это работает, я бы посоветовал вам использовать менеджер версий. Это программа, которая позволяет устанавливать несколько версий Node и переключаться между ними по желанию. Использование менеджера версий имеет различные преимущества, например, он устраняет потенциальные проблемы с разрешениями, которые в противном случае привели бы к установке пакетов с правами администратора.

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

НПМ

npm — менеджер пакетов JavaScript, который поставляется в комплекте с Node, поэтому здесь не требуется дополнительная установка. В этом учебном пособии мы будем широко использовать npm, поэтому, если вам нужна переподготовка, обратитесь к: Руководству по npm для начинающих — Node Package Manager .

MongoDB

MongoDB — это база данных документов, которая хранит данные в гибких JSON-подобных документах.

Самый быстрый способ начать работу с Mongo — это использовать сервис, такой как mLabs. У них есть бесплатный план песочницы, который предоставляет единую базу данных с 496 МБ хранилища, работающего на общей виртуальной машине. Это более чем достаточно для простого приложения с несколькими пользователями. Если это звучит как лучший вариант для вас, пожалуйста, обратитесь к их краткому руководству .

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

MongoDB GUI

Хотя это не является обязательным условием для следования этому руководству, вы также можете установить Compass, официальный графический интерфейс для MongoDB . Этот инструмент помогает вам визуализировать и манипулировать вашими данными, позволяя вам взаимодействовать с документами с полной функциональностью CRUD.

На момент написания, вам нужно будет заполнить свои данные, чтобы загрузить Compass, но вам не нужно создавать учетную запись.

Убедитесь, что все установлено правильно

Чтобы убедиться, что Node и npm установлены правильно, откройте ваш терминал и введите:

node -v 

с последующим:

 npm -v 

Это выведет номер версии каждой программы ( 8.9.4 и 5.6.0 соответственно на момент написания).

Если вы установили Mongo локально, вы можете проверить номер версии, используя:

 mongo --version 

Это должно вывести кучу информации, включая номер версии ( 3.6.2 на момент написания).

Проверьте соединение с базой данных с помощью компаса

Если вы установили Mongo локально, вы запускаете сервер, введя в терминал следующую команду:

 mongod 

Далее откройте Компас. Вы должны быть в состоянии принять значения по умолчанию (сервер: localhost , порт: 27017), нажать кнопку CONNECT и установить соединение с сервером базы данных.

MongoDB Compass подключен к локальному хосту: 27107

MongoDB Compass подключен к локальному хосту

Обратите внимание, что базы данных admin и local создаются автоматически.

Использование облачного решения

Если вы используете mLabs, создайте подписку на базу данных (как описано в их кратком руководстве ), затем скопируйте сведения о соединении в буфер обмена. Это должно быть в форме:

 mongodb://<dbuser>:<dbpassword>@ds251827.mlab.com:51827/<dbname> 

Когда вы откроете Compass, он сообщит вам, что обнаружил строку подключения MongoDB, и спросит, хотите ли вы использовать ее для заполнения формы. Нажмите Да , отметив, что вам может потребоваться изменить имя пользователя и пароль вручную. После этого нажмите CONNECT, и вы должны отправиться в гонки.

MongoDB Compass подключен к mLabs

MongoDB Compass подключен к mLabs

Обратите внимание, что я назвал свою базу данных sp-node-article . Вы можете называть свои так, как вам нравится.

Инициализировать приложение

Когда все настроено правильно, первое, что нам нужно сделать, это инициализировать наш новый проект. Для этого создайте папку с именем demo-node-app , введите этот каталог и введите в терминале следующее:

 npm init -y 

Это создаст и автоматически заполнит файл package.json в корне проекта. Мы можем использовать этот файл для определения наших зависимостей и создания различных сценариев npm , которые помогут нашему процессу разработки.

Установить Экспресс

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

Итак, давайте установим Express . Для этого запустите в своем терминале следующее:

 npm install --save express 

--save опцию --save команде npm install , Express будет добавлен в раздел dependencies файла package.json . Для всех, кто запускает наш код, это говорит о том, что Express — это пакет, необходимый для правильной работы нашего приложения.

Установить nodemon

nodemon — это удобный инструмент. Он будет просматривать файлы в каталоге, в котором он был запущен, и, если обнаружит какие-либо изменения, он автоматически перезапустит ваше приложение Node (то есть вам не нужно). В отличие от Express, nodemon — это не то, что требуется приложению для правильной работы (оно просто помогает нам в разработке), поэтому установите его, используя:

 npm install --save-dev nodemon 

Это добавит nodemon в раздел dev-dependencies файла package.json .

Создайте несколько исходных файлов

Мы почти закончили с настройкой. Все, что нам нужно сделать сейчас, это создать пару исходных файлов перед тем, как запустить приложение.

В папке demo-node-app создайте файл start.js файл start.js . Также создайте папку routes с файлом index.js внутри. После того, как вы закончите, все должно выглядеть так:

 . ├── app.js ├── node_modules │ └── ... ├── package.json ├── routes │ └── index.js └── start.js 

Теперь давайте добавим код к этим файлам.

В app.js :

 const express = require('express'); const routes = require('./routes/index'); const app = express(); app.use('/', routes); module.exports = app; 

Здесь мы импортируем как express модуль, так и (значение экспорта) наш файл маршрутов в приложение. Функция require которую мы используем для этого, — это встроенная функция Node, которая импортирует объект из другого файла или модуля. Если вы хотите освежить в памяти информацию об импорте и экспорте модулей, прочитайте раздел Понимание module.exports и экспорт в Node.js.

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

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

В start.js :

 const app = require('./app'); const server = app.listen(3000, () => { console.log(`Express is running on port ${server.address().port}`); }); 

Здесь мы импортируем приложение Express, которое мы создали в app.js (обратите внимание, что мы можем оставить .js вне имени файла в инструкции require ). Затем мы сообщаем нашему приложению прослушивать порт 3000 для входящих соединений и выводить сообщение на терминал, чтобы указать, что сервер работает.

И в routes/index.js :

 const express = require('express'); const router = express.Router(); router.get('/', (req, res) => { res.send('It works!'); }); module.exports = router; 

Здесь мы импортируем Express в наш файл маршрутов и затем извлекаем из него маршрутизатор. Затем мы используем маршрутизатор для ответа на любые запросы к корневому URL-адресу (в данном случае http://localhost:3000 ) сообщением «Это работает!».

Начните приложение

Наконец, давайте добавим скрипт npm, чтобы nodemon начал наблюдать за нашим приложением. Измените раздел scripts файла package.json чтобы он выглядел следующим образом:

 "scripts": { "watch": "nodemon ./start.js" }, 

Свойство scripts файла package.json чрезвычайно полезно, поскольку позволяет указать произвольные сценарии для запуска в различных сценариях. Это означает, что вам не нужно многократно набирать длинные команды с трудным для запоминания синтаксисом. Если вы хотите узнать больше о том, что могут делать скрипты npm, прочитайте Give Grunt the Boot! Руководство по использованию npm в качестве инструмента сборки .

Теперь введите npm run watch из терминала и зайдите на http: // localhost: 3000 .

Вы должны увидеть «Это работает!»

Основные шаблоны с мопсом

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

Механизм шаблонов позволяет вам использовать статические файлы шаблонов в вашем приложении. Во время выполнения механизм шаблонов заменяет переменные в файле шаблона фактическими значениями и преобразует шаблон в файл HTML, отправляемый клиенту.

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

Создайте папку с именем views и в этой папке файл с именем form.pug . Добавьте следующий код в этот новый файл:

 form(action="." method="POST") label(for="name") Name: input( type="text" id="name" name="name" ) label(for="email") Email: input( type="email" id="email" name="email" ) input(type="submit" value="Submit") 

Как вы можете понять из окончания файла, мы будем использовать движок шаблонов pug в нашем приложении. Pug (ранее известный как Jade) имеет собственный чувствительный к отступам синтаксис для написания динамического и многократно используемого HTML. Надеюсь, что приведенный выше пример легко следовать, но если у вас возникнут трудности с пониманием того, что он делает, просто подождите, пока мы не просмотрим это в браузере, а затем просмотрите исходный код страницы, чтобы увидеть созданную им разметку.

Если вы хотите освежить в памяти информацию о том, что такое шаблоны JavaScript и / или движки шаблонов, и когда вам следует их использовать, прочтите «Обзор шаблонов JavaScript» .

Установите Pug и интегрируйте его в приложение Express

Далее нам нужно установить pug, сохранив его как зависимость:

 npm i --save pug 

Затем настройте app.js для использования Pug в качестве движка макета и поиска шаблонов в папке представлений:

 const express = require('express'); const path = require('path'); const routes = require('./routes/index'); const app = express(); app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'pug'); app.use('/', routes); module.exports = app; 

Вы заметите, что нам также требуется собственный модуль Path Node, который предоставляет утилиты для работы с путями файлов и каталогов. Этот модуль позволяет нам построить путь к нашей папке представлений, используя ее метод join и __dirname (который возвращает каталог, в котором находится исполняемый в данный момент скрипт).

Измените маршрут, чтобы использовать наш шаблон

Наконец, нам нужно указать наш маршрут, чтобы использовать наш новый шаблон. В routes/index.js :

 router.get('/', (req, res) => { res.render('form'); }); 

При этом используется метод рендеринга объекта ответа Express для отправки визуализированного представления клиенту.

Итак, давайте посмотрим, сработало ли это. Поскольку мы используем nodemon, чтобы следить за изменениями в нашем приложении, вы просто должны обновить свой браузер и увидеть наш шедевр брутализма.

Определить файл макета для мопса

Если вы откроете браузер и осмотрите исходный код страницы, то увидите, что Express отправил только HTML-код для формы: на нашей странице отсутствует объявление типа документа, а также раздел заголовка и тела. Давайте исправим это, создав мастер-макет для всех наших шаблонов.

Для этого создайте файл layout.pug в папке представлений и добавьте следующий код:

 doctype html html head title= `${title}` body h1 My Amazing App block content 

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

Второе, на что следует обратить внимание, это строка, которая начинается с ключевого слова block . В шаблоне блок — это просто «блок» Pug, который может заменить дочерний шаблон. Вскоре мы увидим, как его использовать, но если вы хотите узнать больше, прочитайте эту страницу на сайте Pug .

Используйте файл макета из дочернего шаблона

Осталось только сообщить нашему шаблону form.pug что он должен использовать файл макета. Для этого views/form.pug , вот так:

 extends layout block content form(action="." method="POST") label(for="name") Name: input( type="text" id="name" name="name" ) label(for="email") Email: input( type="email" id="email" name="email" ) input(type="submit" value="Submit") 

И в routes/index.js нам нужно передать соответствующий заголовок для отображения шаблона:

 router.get('/', (req, res) => { res.render('form', { title: 'Registration form' }); }); 

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

Работа с формами в Экспресс

В настоящее время, если вы нажмете кнопку « Отправить» в нашей форме, вы будете перенаправлены на страницу с сообщением «Cannot POST /». Это потому, что при отправке наша форма отправляет свое содержимое обратно в / и мы еще не определили маршрут для обработки этого.

Давайте сделаем это сейчас. Добавьте следующее в routes/index.js :

 router.post('/', (req, res) => { res.render('form', { title: 'Registration form' }); }); 

Это то же самое, что и наш маршрут GET, за исключением того, что мы используем router.post для ответа на другой HTTP-глагол.

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

Обработка ввода формы

Следующая задача — получить любые данные, которые пользователь отправил через форму. Для этого нам нужно установить пакет с именем body-parser , который сделает данные формы доступными в теле запроса:

 npm install --save body-parser 

Мы также должны указать нашему приложению использовать этот пакет, поэтому добавьте в app.js следующее:

 const bodyParser = require('body-parser'); ... app.use(bodyParser.urlencoded({ extended: true })); app.use('/', routes); module.exports = app; 

Обратите внимание, что существуют различные способы форматирования данных, которые вы отправляете на сервер, и использование метода urlencoded body-parser позволяет нам обрабатывать данные, отправленные как application/x-www-form-urlencoded .

Затем мы можем попробовать записать отправленные данные в терминал. Измените обработчик маршрута следующим образом:

 router.post('/', (req, res) => { console.log(req.body); res.render('form', { title: 'Registration form' }); }); 

Теперь, когда вы отправляете форму, вы должны увидеть что-то вроде:

 {name: 'Jim', email: '[email protected]'} 

Вывод формы зарегистрирован в терминал

Вывод формы зарегистрирован в терминал

Примечание об объектах запроса и ответа

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

 router.METHOD(route, (req, res) => { // callback function }); 

Функция обратного вызова выполняется всякий раз, когда кто-то посещает URL, который соответствует указанному маршруту. Обратный вызов получает параметр req и res , где req — это объект, полный информации, которая поступает (например, данные формы или параметры запроса), а res — это объект, полный методов для отправки данных обратно пользователю. Существует также необязательный параметр next который полезен, если вы на самом деле не хотите отправлять какие-либо данные назад или если вы хотите передать запрос для обработки чего-то еще.

Не вдаваясь слишком глубоко в сорняки, это понятие, известное как промежуточное ПО (в частности, промежуточное ПО уровня маршрутизатора), которое очень важно в Express. Если вы хотите узнать больше о том, как Express использует промежуточное ПО, я рекомендую вам прочитать документы Express .

Подтверждение ввода формы

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

Вы можете установить его так:

 npm install express-validator --save 

И потребуем функции, которые нам понадобятся в routes/index.js :

 const { body, validationResult } = require('express-validator/check'); 

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

 router.post('/', [ body('name') .isLength({ min: 1 }) .withMessage('Please enter a name'), body('email') .isLength({ min: 1 }) .withMessage('Please enter an email'), ], (req, res) => { ... } ); 

Как видите, мы используем метод body для проверки двух свойств в req.body а именно name и email . В нашем случае достаточно просто проверить, что эти свойства существуют (то есть они имеют длину больше единицы), но экспресс-валидатор предлагает целый ряд других методов, о которых вы можете прочитать на домашней странице проекта .

На втором шаге мы можем вызвать метод validationResult, чтобы проверить, прошла ли валидация или нет. Если ошибок нет, мы можем продолжить и отправить сообщение «Спасибо за регистрацию». В противном случае нам нужно будет передать эти ошибки обратно в наш шаблон, чтобы сообщить пользователю, что что-то не так.

И если проверка не req.body , нам также нужно будет передать req.body обратно в шаблон, чтобы любые допустимые входные данные формы не сбрасывались:

 router.post( '/', [ ... ], (req, res) => { const errors = validationResult(req); if (errors.isEmpty()) { res.send('Thank you for your registration!'); } else { res.render('form', { title: 'Registration form', errors: errors.array(), data: req.body, }); } } ); 

Теперь нам нужно внести пару изменений в наш шаблон form.pug . Во-первых, нам нужно проверить свойство errors и, если оно есть, зациклить все ошибки и отобразить их в списке:

 extends layout block content if errors ul for error in errors li= error.msg ... 

Если li= выглядит странно, помните, что pug выполняет интерполяцию, следуя имени тега со знаком равенства.

Наконец, нам нужно проверить, существует ли атрибут data , и если да, использовать его для установки значений соответствующих полей. Если он не существует, мы инициализируем его как пустой объект, так что форма все равно будет корректно отображаться при первой загрузке. Мы можем сделать это с помощью некоторого JavaScript, обозначенного в Pug знаком минус:

 -data = data || {} 

Затем мы ссылаемся на этот атрибут, чтобы установить значение поля:

 input( type="text" id="name" name="name" value=data.name ) 

Это дает нам следующее:

 extends layout block content -data = data || {} if errors ul for error in errors li= error.msg form(action="." method="POST") label(for="name") Name: input( type="text" id="name" name="name" value=data.name ) label(for="email") Email: input( type="email" id="email" name="email" value=data.email ) input(type="submit" value="Submit") 

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

Взаимодействовать с базой данных

Теперь мы хотим подключить нашу форму к нашей базе данных, чтобы мы могли сохранять любые данные, которые вводит пользователь. Если вы используете Mongo локально, не забудьте запустить сервер командой mongod .

Укажите детали подключения

Нам нужно где-то указать детали подключения к нашей базе данных. Для этого мы будем использовать файл конфигурации (который не должен проверяться в управлении версиями) и пакет dotenv . Dotenv загрузит наши данные соединения из файла конфигурации в файл Node’s process.env .

Установите это так:

 npm install dotenv --save 

И требуется это в начале start.js :

 require('dotenv').config(); 

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

Если вы используете Mongo локально:

 DATABASE=mongodb://localhost:27017/node-demo-application 

Если вы используете mLabs:

 mongodb://<dbuser>:<dbpassword>@ds251827.mlab.com:51827/<dbname> 

Обратите внимание, что локальные установки MongoDB не имеют пользователя или пароля по умолчанию. Это определенно то, что вы захотите изменить в производстве, так как в противном случае это угроза безопасности.

Подключиться к базе данных

Чтобы установить соединение с базой данных и выполнить над ней операции, мы будем использовать Mongoose . Mongoose — это ORM для MongoDB, и, как вы можете прочитать на домашней странице проекта :

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

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

Чтобы установить Mongoose:

 npm install --save mongoose 

Затем, start.js это в start.js :

 const mongoose = require('mongoose'); 

Соединение сделано так:

 mongoose.connect(process.env.DATABASE, { useMongoClient: true }); mongoose.Promise = global.Promise; mongoose.connection .on('connected', () => { console.log(`Mongoose connection open on ${process.env.DATABASE}`); }) .on('error', (err) => { console.log(`Connection error: ${err.message}`); }); 

Обратите внимание, как мы используем переменную DATABASE мы объявили в файле .env чтобы указать URL базы данных. Мы также призываем Mongo использовать обещания ES6 (это необходимо, поскольку взаимодействие с базой данных асинхронно), поскольку его собственная библиотека обещаний по умолчанию устарела.

Вот как должен выглядеть start.js :

 require('dotenv').config(); const mongoose = require('mongoose'); mongoose.connect(process.env.DATABASE, { useMongoClient: true }); mongoose.Promise = global.Promise; mongoose.connection .on('connected', () => { console.log(`Mongoose connection open on ${process.env.DATABASE}`); }) .on('error', (err) => { console.log(`Connection error: ${err.message}`); }); const app = require('./app'); const server = app.listen(3000, () => { console.log(`Express is running on port ${server.address().port}`); }); 

Когда вы сохраните файл, nodemon перезапустит приложение и, если все прошло хорошо, вы должны увидеть что-то вроде:

 Mongoose connection open on mongodb://localhost:27017/node-demo-application 

Определить схему мангуста

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

Для этого создайте папку models в корневом каталоге проекта, а внутри нее — новый файл с именем Registration.js .

Добавьте следующий код в Registration.js :

 const mongoose = require('mongoose'); const registrationSchema = new mongoose.Schema({ name: { type: String, trim: true, }, email: { type: String, trim: true, }, }); module.exports = mongoose.model('Registration', registrationSchema); 

Здесь мы просто определяем тип (как у нас уже есть валидация) и используем вспомогательный метод trim для удаления любого лишнего пробела из пользовательского ввода. Затем мы компилируем модель из определения схемы и экспортируем ее для использования в другом месте нашего приложения.

Последняя часть шаблона должна требовать модель в start.js :

 ... require('./models/Registration'); const app = require('./app'); const server = app.listen(3000, () => { console.log(`Express is running on port ${server.address().port}`); }); 

Сохранить данные в базе данных

Теперь мы готовы сохранить пользовательские данные в нашей базе данных. Начнем с требования Mongoose и импорта нашей модели в наш файл routes/index.js :

 const express = require('express'); const mongoose = require('mongoose'); const { body, validationResult } = require('express-validator/check'); const router = express.Router(); const Registration = mongoose.model('Registration'); ... 

Теперь, когда пользователь отправляет данные на сервер, если проверка прошла успешно, мы можем продолжить и создать новый объект Registration и попытаться сохранить его. Поскольку операция с базой данных является асинхронной операцией, которая возвращает Promise, мы можем .then() в конце, чтобы справиться с успешной вставкой, и .catch() чтобы справиться с любыми ошибками:

 if (errors.isEmpty()) { const registration = new Registration(req.body); registration.save() .then(() => { res.send('Thank you for your registration!'); }) .catch(() => { res.send('Sorry! Something went wrong.'); }); } else { ... } ... 

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

Используя Compass, чтобы проверить, что наши данные были сохранены в MongoDB

Используя Compass, чтобы проверить, что наши данные были сохранены в MongoDB

Получить данные из базы данных

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

Добавьте новый маршрут к routes/index.js следующим образом:

 router.get('/registrations', (req, res) => { res.render('index', { title: 'Listing registrations' }); }); 

Это означает, что нам также понадобится соответствующий шаблон представления ( views/index.pug ):

 extends layout block content p No registrations yet 🙁 

Теперь, когда вы посещаете http: // localhost: 3000 / registrations , вы должны увидеть сообщение о том, что никаких регистраций нет.

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

В routes/index.js :

 router.get('/registrations', (req, res) => { Registration.find() .then((registrations) => { res.render('index', { title: 'Listing registrations', registrations }); }) .catch(() => { res.send('Sorry! Something went wrong.'); }); }); 

Здесь мы используем метод Collection # find Монго, который, если вызывается без параметров, возвращает все записи в коллекции. Поскольку поиск в базе данных является асинхронным, мы ждем его завершения, прежде чем отображать представление. Если какие-либо записи были возвращены, они будут переданы в шаблон представления в свойстве registrations . Если не было возвращено ни одной записи, registrations будут пустым массивом.

В views/index.pug мы можем затем проверить длину того, что нам передали, и либо зациклить его, и вывести записи на экран, либо отобразить сообщение «Нет регистрации»:

 extends layout block content if registrations.length table tr th Name th Email each registration in registrations tr td= registration.name td= registration.email else p No registrations yet 🙁 

Добавить HTTP-аутентификацию

Последняя функция, которую мы добавим в наше приложение, — HTTP-аутентификация , блокирующая список успешных регистраций от посторонних глаз.

Для этого мы будем использовать модуль http-auth , который мы можем установить с помощью:

 npm install --save http-auth 

Далее нам нужно это сделать в routes/index.js вместе с модулем Path, с которым мы встречались ранее:

 const path = require('path'); const auth = require('http-auth'); 

Затем сообщите ему, где найти файл, в котором мы перечислим пользователей и пароли (в данном случае users.htpasswd в корне проекта):

 const basic = auth.basic({ file: path.join(__dirname, '../users.htpasswd'), }); 

users.htpasswd создайте этот файл users.htpasswd и добавьте имя пользователя и пароль, разделенные двоеточием. Это может быть простой текст, но модуль http-auth также поддерживает хешированные пароли, поэтому вы также можете запустить пароль через службу, такую ​​как Htpasswd Generator .

Для меня содержимое users.htpasswd выглядит так:

 jim:$apr1$FhFmamtz$PgXfrNI95HFCuXIm30Q4V0 

Это переводит пользователя: jim , пароль: password .

Наконец, добавьте его к маршруту, который вы хотите защитить, и вы готовы идти:

 router.get('/registrations', auth.connect(basic), (req, res) => { ... }); 

Служить статическим активам в экспрессе

Давайте немного доработаем приложение и добавим стили с помощью Twitter Bootstrap . Мы можем обслуживать статические файлы, такие как изображения, файлы JavaScript и файлы CSS в Express, используя встроенную функцию промежуточного программного обеспечения express.static .

Настроить это легко. Просто добавьте следующую строку в app.js :

 app.use(express.static('public')); 

Теперь мы можем загружать файлы, которые находятся в public directory .

Разработайте приложение с помощью Bootstrap

Создайте public каталог в корневом каталоге проекта, а в public каталоге создайте каталог css . Загрузите уменьшенную версию Bootstrap v4 в этот каталог, убедившись, что она называется bootstrap.min.css .

Далее нам нужно добавить разметку в наши шаблоны мопса.

В layout.pug :

 doctype html html head title= `${title}` link(rel='stylesheet', href='/css/bootstrap.min.css') link(rel='stylesheet', href='/css/styles.css') body div.container.listing-reg h1 My Amazing App block content 

Здесь мы включаем два файла из нашей ранее созданной папки css и добавляем div-оболочку.

В form.pug мы добавляем имена некоторых классов к сообщениям об ошибках и элементам формы:

 extends layout block content -data = data || {} if errors ul.my-errors for error in errors li= error.msg form(action="." method="POST" class="form-registration") label(for="name") Name: input( type="text" id="name" name="name" class="form-control" value=data.name ) label(for="email") Email: input( type="email" id="email" name="email" class="form-control" value=data.email ) input( type="submit" value="Submit" class="btn btn-lg btn-primary btn-block" ) 

И в index.pug , больше того же самого:

 extends layout block content if registrations.length table.listing-table.table-dark.table-striped tr th Name th Email each registration in registrations tr td= registration.name td= registration.email else p No registrations yet 🙁 

Наконец, создайте файл с именем styles.css в папке css и добавьте следующее:

 body { padding: 40px 10px; background-color: #eee; } .listing-reg h1 { text-align: center; margin: 0 0 2rem; } /* css for registration form and errors*/ .form-registration { max-width: 330px; padding: 15px; margin: 0 auto; } .form-registration { display: flex; flex-wrap: wrap; } .form-registration input { width: 100%; margin: 0px 0 10px; } .form-registration .btn { flex: 1 0 100%; } .my-errors { margin: 0 auto; padding: 0; list-style: none; color: #333; font-size: 1.2rem; display: table; } .my-errors li { margin: 0 0 1rem; } .my-errors li:before { content: "! Error : "; color: #f00; font-weight: bold; } /* Styles for listing table */ .listing-table { width: 100%; } .listing-table th, .listing-table td { padding: 10px; border-bottom: 1px solid #666; } .listing-table th { background: #000; color: #fff; } .listing-table td:first-child, .listing-table th:first-child { border-right: 1px solid #666; } 

Теперь, когда вы обновите страницу, вы должны увидеть всю славу Bootstrap!

Вывод

Я надеюсь, вам понравился этот урок. Хотя мы не создавали следующий Facebook, я надеюсь, что я все же смог помочь вам погрузиться в мир веб-приложений, основанных на Node, и предложить вам несколько полезных идей для вашего следующего проекта.

Конечно, сложно охватить все в одном уроке, и есть много способов уточнить, что мы здесь создали. Например, вы можете проверить нашу статью о развертывании приложений Node и попробовать запустить ее на Heroku или сейчас . В качестве альтернативы вы можете дополнить функциональность CRUD возможностью удалять регистрации или даже написать пару тестов для проверки функциональности приложения.

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