Разработка сайтов в Луганске, ЛНР. Создайте простое приложение для начинающих с Node, Bootstrap и MongoDB

 
 

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

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

В этом уроке я собираюсь использовать немного другой подход. Начиная с нуля, я покажу, как создать простое веб-приложение с помощью 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.

MongoDB

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

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

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

Графический интерфейс MongoDB

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

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

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

node -v

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

npm -v

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

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

mongo —version

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

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

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

mongod

Затем откройте Компас. Вы должны принять значения по умолчанию (сервер: localhost, порт: 27017), нажать кнопку ПОДКЛЮЧИТЬСЯ и установить соединение с сервером базы данных.

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

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

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

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

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

Откройте Compass, нажмите «Новое подключение «, затем заполните поля подключения по отдельности. Выберите имя пользователя/пароль в качестве метода аутентификации, затем заполните остальные данные. Наконец, нажмите ПОДКЛЮЧИТЬСЯ, и вы должны отправиться в гонки.

Примечание: если вы хотите использовать строку подключения, она должна выглядеть так: mongodb: //: @ds211709.mlab.com:11709/? authSource=.

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 express

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

Установить нодмон

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

npm install —save-dev nodemon

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

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

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

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

.

├── app.js

├── node_modules

│ └──...

├── package.json

├── package-lock.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, используя экспресс — функцию и присваивая ее 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. (Обратите внимание, что мы можем оставить.jsoff имя файла в 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, прочитайте «Дай Grunt the Boot! «Руководство по использованию npm в качестве инструмента сборки.

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

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

Основные шаблоны с Pug

Возврат встроенного ответа из обработчика маршрута — это хорошо, но он не очень расширяемый, и именно здесь вступают в действие механизмы шаблонов. Как говорится в документации 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. Надеемся, приведенному выше примеру легко следовать, но если у вас есть какие-либо трудности с пониманием того, что он делает, просто подождите, пока мы просмотрим его в браузере, а затем проверьте исходный код страницы, чтобы увидеть разметку, которую он создает.

Если вы хотите узнать немного больше о Pug, прежде чем продолжить, прочитайте наш учебник A Beginner’s Guide to Pug.

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

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

npm install pug

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

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;

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

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

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

router.get ('/', (req, res) => {

res.render ('form’) ;

}) ;

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

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

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

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

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

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’ }) ;

}) ;

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

Работа с формами в Express

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

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

router.post ('/', (req, res) => {

res.render ('form’, { title: 'Registration form’ }) ;

}) ;

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

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

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

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

npm install 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: 'jim@example.com’}

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

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

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

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

router.METHOD (route, (req, res) => {

// callback function

}) ;

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

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

Проверка ввода формы

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

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

npm install express-validator

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

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

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

router.post ('/',

[

check ('name’)

.isLength ({ min: 1 })

.withMessage ('Please enter a name’),

check ('email’)

.isLength ({ min: 1 })

.withMessage ('Please enter an email’),

],

(req, res) => {

...

}) ;

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

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

И если проверка не пройдена, нам также нужно будет 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

)

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

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

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

И требуйте его в верхней части start.js:

require ('dotenv’).config () ;

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

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

DATABASE=mongodb: //localhost:27017/

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

DATABASE=mongodb: //: @ds211709.mlab.com:11709/? authSource=

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

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

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

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

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

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

npm install mongoose

Затем потребуйте его в start.js:

const mongoose = require ('mongoose’) ;

Подключение делается так:

mongoose.connect (process.env.DATABASE, {

useNewUrlParser: true,

useUnifiedTopology: true

}) ;

mongoose.connection

.on ('open’, () => {

console.log ('Mongoose connection open’) ;

})

.on ('error’, (err) => {

console.log (`Connection error: ${err.message}`) ;

}) ;

Обратите внимание, как мы используем DATABASEпеременную, объявленную в.envфайле, для указания URL-адреса базы данных.

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

require ('dotenv’).config () ;

const mongoose = require ('mongoose’) ;

mongoose.connect (process.env.DATABASE, {

useNewUrlParser: true,

useUnifiedTopology: true

}) ;

mongoose.connection

.on ('open’, () => {

console.log ('Mongoose connection open’) ;

})

.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 открыто».

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

MongoDB можно использовать как свободную базу данных, то есть нет необходимости заранее описывать, как будут выглядеть данные. Однако мы используем Mongoose для взаимодействия с ним, и все в Mongoose начинается со схемы. В Mongoose каждая схема сопоставляется с коллекцией 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) ;

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

Последняя часть шаблона — потребовать модель в 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 { check, validationResult } = require ('express-validator’) ;

const router = express.Router () ;

const Registration = mongoose.model ('Registration’) ;

...

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

if (errors.isEmpty ()) {

const registration = new Registration (req.body) ;

registration.save ()

.then (() => { res.send ('Thank you for your registration!') ; })

.catch ((err) => {

console.log (err) ;

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.') ; }) ;

}) ;

Здесь мы используем метод Mongo 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 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файл и добавьте имя пользователя и пароль, разделенные двоеточием. Это может быть обычный текст, но модуль http-auth также поддерживает хешированные пароли, поэтому вы также можете запустить пароль через службу, такую ​​как Htpasswd Generator.

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

jim: $apr$1FhFmamtz$PgXfrNI95HFCuXIm30Q4V0

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

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

router.get ('/registrations’, basic.check ((req, res) => {

...

}));

Подавать статические активы в Express

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

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

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

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

Стилизуйте приложение с помощью 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 возможностью удаления регистраций или даже написать пару тестов для проверки функциональности приложения.

3D-печать5GABC-анализAndroidAppleAppStoreAsusCall-центрChatGPTCRMDellDNSDrupalExcelFacebookFMCGGoogleHuaweiInstagramiPhoneLinkedInLinuxMagentoMicrosoftNvidiaOpenCartPlayStationPOS материалPPC-специалистRuTubeSamsungSEO-услугиSMMSnapchatSonyStarlinkTikTokTwitterUbuntuUp-saleViasatVPNWhatsAppWindowsWordPressXiaomiYouTubeZoomАвдеевкаАктивные продажиАкцияАлександровск ЛНРАлмазнаяАлчевскАмвросиевкаАнализ конкурентовАнализ продажАнтимерчандайзингАнтрацитАртемовскАртемовск ЛНРАссортиментная политикаБелгородБелицкоеБелозерскоеБердянскБизнес-идеи (стартапы)БрендБрянкаБукингВахрушевоВендорВидеоВикипедияВирусная рекламаВирусный маркетингВладивостокВнутренние продажиВнутренний маркетингВолгоградВолновахаВоронежГорловкаГорнякГорскоеДебальцевоДебиторкаДебиторская задолженностьДезинтермедитацияДзержинскДивизионная система управленияДизайнДимитровДирект-маркетингДисконтДистрибьюторДистрибьюцияДобропольеДокучаевскДоменДружковкаЕкатеринбургЕнакиевоЖдановкаЗапорожьеЗимогорьеЗолотоеЗоринскЗугрэсИжевскИловайскИрминоКазаньКалининградКировскКировскоеКомсомольскоеКонстантиновкаКонтент-маркетингКонтент-планКопирайтингКраматорскКрасноармейскКрасногоровкаКраснодарКраснодонКраснопартизанскКрасный ЛиманКрасный ЛучКременнаяКураховоКурскЛисичанскЛуганскЛутугиноМакеевкаМариупольМаркетингМаркетинговая информацияМаркетинговые исследованияМаркетинговый каналМаркетинг услугМаркетологМарьинкаМедиаМелекиноМелитопольМенеджментМерчандайзерМерчандайзингМиусинскМолодогвардейскМоскваМоспиноНижний НовгородНиколаевНиколаевкаНишевой маркетингНовоазовскНовогродовкаНоводружескНовосибирскНумерическая дистрибьюцияОдессаОмскОтдел маркетингаПартизанский маркетингПервомайскПеревальскПетровскоеПлата за кликПоисковая оптимизацияПопаснаяПравило ПаретоПривольеПрогнозирование продажПродвижение сайтов в ДонецкеПроизводство видеоПромоПромоушнПрямой маркетингРабота для маркетологаРабота для студентаРазработка приложенийРаспродажаРегиональные продажиРекламаРеклама на асфальтеРемаркетингРетро-бонусРибейтРитейлРовенькиРодинскоеРостов-на-ДонуРубежноеСамараСанкт-ПетербургСаратовСватовоСвердловскСветлодарскСвятогорскСевастопольСеверодонецкСеверскСедовоСейлз промоушнСелидовоСимферопольСинергияСколковоСлавянскСнежноеСоздание сайтов в ДонецкеСоледарСоциальные сетиСочиСтаробельскСтаробешевоСтахановСтимулирование сбытаСуходольскСчастьеТелемаркетингТельмановоТираспольТорговый представительТорезТрейд маркетингТрейд промоушнТюменьУглегорскУгледарУкраинскХабаровскХарцызскХерсонХостингЦелевая аудиторияЦифровой маркетингЧасов ЯрЧелябинскШахтерскЮжно-СахалинскЮнокоммунаровскЯндексЯсиноватая