Упражнение. Создание базового веб-приложения
До сих пор вы установили MongoDB и Node.js на виртуальной машине Ubuntu. Теперь пора создать базовое веб-приложение, чтобы увидеть все это в действии. По пути вы увидите, как AngularJS и Express вписываются в.
Лучше всего учиться на примере. Веб-приложение, которое вы создаете, реализует базовую базу данных книги. Веб-приложение позволяет перечислять сведения о книгах, добавлять новые книги и удалять существующие книги.
Веб-приложение, которое вы видите здесь, демонстрирует множество концепций, которые применяются к большинству веб-приложений стека стека. Исходя из ваших потребностей и интересов, изучите возможности, необходимые для создания ваших приложений в стеке MEAN.
Вот как выглядит веб-приложение книг.
Вот какую роль играет каждый компонент стека MEAN.
- MongoDB хранит сведения о книгах.
- Express.js направляет каждый HTTP-запрос в соответствующий обработчик.
- AngularJS соединяет пользовательский интерфейс с бизнес-логикой программы.
- Node.js размещает приложение на стороне сервера.
Внимание
В целях обучения здесь вы создаете базовое веб-приложение. Вы изучаете стек MEAN и принципы его работы. Приложение недостаточно безопасно или готово для использования в рабочей среде.
Как насчет Express?
До сих пор вы установили MongoDB и Node.js на виртуальной машине. Как насчет Express.js — E в акрониме MEAN?
Express.js — это платформа веб-сервера, созданная для Node.js, которая упрощает процесс создания веб-приложений.
Основная цель Express — обрабатывать маршрутизацию запросов.
Маршрутизация определяет, как приложение отвечает на запрос к конкретной конечной точке. Конечная точка состоит из пути или URI, а также метода запроса, например GET или POST. Например, вы можете ответить на запрос GET к конечной точке /book
, предоставив список всех книг в базе данных. Вы можете ответить на запрос POST к /book
конечной точке, добавив запись в базу данных на основе полей, введенных пользователем в веб-форму.
В веб-приложении, которое вы создаете вскоре, вы используете Express для маршрутизации HTTP-запросов и возврата веб-содержимого пользователю. Express также помогает веб-приложениям работать с файлами cookie HTTP и обрабатывать строки запроса.
Express — это пакет Node.js. Используйте служебную программу npm, которая поставляется с Node.js, для установки пакетов Node.js и управления ими. Далее в этом уроке вы создадите файл с именем package.json
для определения Express и других зависимостей, а затем выполните npm install
команду, чтобы установить эти зависимости.
Как насчет AngularJS?
Как и Express, AngularJS, A в акрониме MEAN, еще не установлен.
AngularJS упрощает запись и тестирование веб-приложений, так как позволяет лучше отделять внешний вид веб-страницы — html-код от того, как работает веб-страница. Если вы знакомы с шаблоном модели -view-controller (MVC) или понятием привязки данных, AngularJS должен быть знаком с вами.
AngularJS — это интерфейсная платформа JavaScript, которая означает, что она должна быть доступна только на клиенте, который обращается к приложению. Иными словами, AngularJS выполняется в веб-браузере пользователя, не на веб-сервере. И поскольку AngularJS — это JavaScript, можно использовать его, чтобы легко извлечь данные с веб-сервера для отображения на странице.
Вы не устанавливаете AngularJS в прямом смысле. Вместо этого вы добавляете ссылку на файл JavaScript на HTML-странице, как вы это делаете с другими библиотеками JavaScript. Существует несколько способов включить AngularJS в веб-страницы. Здесь вы загружаете AngularJS из сети доставки содержимого (CDN). CDN — это способ распределения изображений, видео и другого содержимого географически для повышения скорости загрузки.
Не добавляйте этот код, но вот пример, который загружает AngularJS из CDN. Обычно этот код добавляется в <head>
раздел HTML-страницы.
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.2/angular.min.js"></script>
Примечание.
Не путайте AngularJS с Angular. Хотя многие понятия в них похожи, AngularJS предшествует Angular. AngularJS по-прежнему широко используется для создания веб-приложений. AngularJS основан на JavaScript, а Angular основан на TypeScript, языке программирования, который упрощает написание программ JavaScript.
Разделы справки построить приложение?
Здесь используется базовый процесс. Вы пишете код приложения из Cloud Shell, а затем используете протокол безопасного копирования (SCP), чтобы скопировать файлы на виртуальную машину. Затем запустите приложение Node.js и увидите результаты в браузере.
На практике обычно вы будете писать и тестировать веб-приложение в более локальной среде, например с ноутбука или виртуальной машины, которую вы запускаете локально. Вы можете хранить код в системе управления версиями, например Git. Затем используйте систему непрерывной интеграции и непрерывной доставки (CI/CD), например Azure DevOps, для тестирования изменений и их отправки на виртуальную машину. Мы указываем на дополнительные ресурсы в конце этого модуля.
Создание веб-приложения базы данных с книгами
Здесь вы создадите весь код, скрипт и HTML-файлы, составляющие веб-приложение. Для краткости мы выделите важные части каждого файла, но не получите полных сведений.
Если к виртуальной машине по-прежнему установлено подключение по протоколу SSH, выполните команду exit
, чтобы завершить сеанс SSH и вернуться к Cloud Shell.
exit
Вы вернулись в сеанс Cloud Shell.
Создание файлов
В Cloud Shell выполните следующие команды, чтобы создать папки и файлы для веб-приложения:
cd ~ mkdir Books touch Books/server.js touch Books/package.json mkdir Books/app touch Books/app/model.js touch Books/app/routes.js mkdir Books/public touch Books/public/script.js touch Books/public/index.html
Веб-приложение содержит следующие папки и файлы:
-
Books
— корневой каталог проекта.-
server.js
определяет точку входа в веб-приложение. Он загружает необходимые пакеты Node.js, указывает порт для прослушивания и начинает ожидать входящий HTTP-трафик. -
package.json
предоставляет сведения о приложении, включая имя, описание и необходимые для запуска пакеты Node.js.
-
-
Books/app
содержит код, выполняемый на сервере.-
model.js
определяет подключение к базе данных и схему. Его можно рассматривать как модель данных для приложения. -
routes.js
обрабатывает маршрутизацию запросов. Например, он определяет запросы GET к конечной точке/book
, предоставляя список всех книг в базе данных.
-
-
Books/public
содержит файлы, которые обслуживаются непосредственно в клиентском браузере.-
index.html
содержит страницу индекса. Он содержит веб-форму, которая позволяет пользователям отправлять сведения о книгах. Он также отображает все книги в базе данных и позволяет удалять записи из базы данных. -
script.js
содержит код JavaScript, выполняемый в браузере пользователя. Он может отправлять запросы к серверу, чтобы вывести список книг, добавить книги в базу данных и удалить книги из базы данных.
-
-
Выполните команду
code
, чтобы открыть файлы через редактор Cloud Shell.code Books
Создание модели данных
В редакторе откройте
app/model.js
и добавьте следующий код:var mongoose = require('mongoose'); var dbHost = 'mongodb://localhost:27017/Books'; mongoose.connect(dbHost, { useNewUrlParser: true } ); mongoose.connection; mongoose.set('debug', true); var bookSchema = mongoose.Schema( { name: String, isbn: {type: String, index: true}, author: String, pages: Number }); var Book = mongoose.model('Book', bookSchema); module.exports = Book;
Внимание
Когда вы вставляете фрагменты или изменяете код в файле в редакторе, сохраняйте изменения через меню "..." или используя сочетание клавиш (CTRL+S в Windows и Linux и Command+S в macOS).
Этот код использует Mongoose для упрощения процесса передачи данных в MongoDB и обратно. Mongoose — это система для моделирования данных на основе схемы. Код определяет документ базы данных с именем Book с помощью заданной схемы. Схема определяет четыре поля, которые описывают одну книгу:
- название книги, или заголовок;
- Его международный номер стандартной книги (ISBN), который однозначно идентифицирует книгу
- автора;
- количество страниц.
Затем вы создадите обработчики HTTP, которые сопоставляют запросы GET, POST и DELETE с операциями базы данных.
Создание маршрутов Express.js, которые обрабатывают HTTP-запросы
В редакторе откройте
app/routes.js
и добавьте следующий код:var path = require('path'); var Book = require('./model'); var routes = function(app) { app.get('/book', function(req, res) { Book.find({}, function(err, result) { if ( err ) throw err; res.json(result); }); }); app.post('/book', function(req, res) { var book = new Book( { name:req.body.name, isbn:req.body.isbn, author:req.body.author, pages:req.body.pages }); book.save(function(err, result) { if ( err ) throw err; res.json( { message:"Successfully added book", book:result }); }); }); app.delete("/book/:isbn", function(req, res) { Book.findOneAndRemove(req.query, function(err, result) { if ( err ) throw err; res.json( { message: "Successfully deleted the book", book: result }); }); }); app.get('*', function(req, res) { res.sendFile(path.join(__dirname + '/public', 'index.html')); }); }; module.exports = routes;
Этот код создает четыре маршрута для приложения. Вот краткий обзор каждого.
HTTP-команда Конечная точка Description GET /book
Извлекает все книги из базы данных. POST /book
Создает объект Book
на основе полей, заполненных пользователем в веб-форме, и записывает этот объект в базу данных.DELETE /book/:isbn
Удаляет книги из базы данных по номеру ISBN. GET *
Возвращает страницу индексов при несовпадении маршрутов. Express.js может обслуживать http-ответы непосредственно в коде обработки маршрутов или обслуживать статическое содержимое из файлов. Этот код показывает оба варианта. Первые три маршрута возвращают данные JSON для запросов API книги. Четвертый маршрут (сценарий по умолчанию) возвращает содержимое файла индекса,
index.html
.
Создание клиентского приложения JavaScript
В редакторе откройте файл
public/script.js
и добавьте следующий код:var app = angular.module('myApp', []); app.controller('myCtrl', function($scope, $http) { var getData = function() { return $http( { method: 'GET', url: '/book' }).then(function successCallback(response) { $scope.books = response.data; }, function errorCallback(response) { console.log('Error: ' + response); }); }; getData(); $scope.del_book = function(book) { $http( { method: 'DELETE', url: '/book/:isbn', params: {'isbn': book.isbn} }).then(function successCallback(response) { console.log(response); return getData(); }, function errorCallback(response) { console.log('Error: ' + response); }); }; $scope.add_book = function() { var body = '{ "name": "' + $scope.Name + '", "isbn": "' + $scope.Isbn + '", "author": "' + $scope.Author + '", "pages": "' + $scope.Pages + '" }'; $http({ method: 'POST', url: '/book', data: body }).then(function successCallback(response) { console.log(response); return getData(); }, function errorCallback(response) { console.log('Error: ' + response); }); }; });
Обратите внимание, как этот код определяет модуль с именем
myApp
и контроллером с именемmyCtrl
. Мы не будем подробно останавливаться на том, как здесь работают модуль и контроллеры, но вы используете эти имена в следующем шаге для привязки пользовательского интерфейса (HTML-кода) к бизнес-логике приложения.Ранее вы создали четыре маршрута, которые обрабатывают различные операции GET, POST и DELETE на сервере. Этот код похож на эти же операции, но на стороне клиента (в браузере пользователя).
Функция
getData
, например, отправляет запрос GET к конечной точке/book
. Помните, что сервер обрабатывает этот запрос, извлекая сведения обо всех книгах из базы данных и возвращая эти сведения в виде данных JSON в ответе. Обратите внимание, как данные JSON в ответе назначены переменной$scope.books
. Вы узнаете, как этот код влияет на то, что пользователь видит на веб-странице на следующем шаге.Этот код вызывает функцию
getData
при загрузке страницы. Изучите функцииdel_book
иadd_book
, чтобы понять, как они работают. Вам не нужен клиентский код для сопоставления обработчика по умолчанию сервера, так как обработчик по умолчанию возвращает страницу индекса, а не данные JSON.
Создание пользовательского интерфейса
В редакторе откройте файл
public/index.html
и добавьте следующий код:<!doctype html> <html ng-app="myApp" ng-controller="myCtrl"> <head> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.2/angular.min.js"></script> <script src="script.js"></script> </head> <body> <div> <table> <tr> <td>Name:</td> <td><input type="text" ng-model="Name"></td> </tr> <tr> <td>Isbn:</td> <td><input type="text" ng-model="Isbn"></td> </tr> <tr> <td>Author:</td> <td><input type="text" ng-model="Author"></td> </tr> <tr> <td>Pages:</td> <td><input type="number" ng-model="Pages"></td> </tr> </table> <button ng-click="add_book()">Add</button> </div> <hr> <div> <table> <tr> <th>Name</th> <th>Isbn</th> <th>Author</th> <th>Pages</th> </tr> <tr ng-repeat="book in books"> <td><input type="button" value="Delete" data-ng-click="del_book(book)"></td> <td>{{book.name}}</td> <td>{{book.isbn}}</td> <td>{{book.author}}</td> <td>{{book.pages}}</td> </tr> </table> </div> </body> </html>
Этот код создает базовую HTML-форму с четырьмя полями для отправки данных книг и таблицы, отображающей все книги, хранящиеся в базе данных.
Хотя этот код HTML является стандартным,
ng-
атрибуты HTML могут быть незнакомы для вас. Эти атрибуты HTML подключают код AngularJS к пользовательскому интерфейсу. Например, при нажатии кнопки Добавить AngularJS вызывает функциюadd_book
, которая отправляет данные формы на сервер.Изучите код, чтобы получить представление о том, как каждый из атрибутов
ng-
связан с бизнес-логикой приложения.
Создание сервера Express.js для размещения приложения
В редакторе откройте файл
server.js
и добавьте следующий код:var express = require('express'); var bodyParser = require('body-parser'); var app = express(); app.use(express.static(__dirname + '/public')); app.use(bodyParser.json()); require('./app/routes')(app); app.set('port', 80); app.listen(app.get('port'), function() { console.log('Server up: http://localhost:' + app.get('port')); });
Этот код создает веб-приложение. Он обслуживает статические файлы из
public
каталога и использует маршруты, определенные ранее для обработки запросов.
Определение сведений о пакете и зависимостей
Как вы помните, package.json
предоставляет сведения о приложении, включая имя, описание и необходимые для запуска пакеты Node.js.
В редакторе откройте файл
package.json
и добавьте следующий код:{ "name": "books", "description": "Sample web app that manages book information.", "license": "MIT", "repository": { "type": "git", "url": "https://github.com/MicrosoftDocs/mslearn-build-a-web-app-with-mean-on-a-linux-vm" }, "main": "server.js", "dependencies": { "express": "~4.16", "mongoose": "~5.3", "body-parser": "~1.18" } }
Вы увидите данные или метаданные о своем приложении, включая его имя, описание и лицензию.
Поле repository
указывает, где размещен код. Для справки вы можете позже просмотреть код на GitHub по URL-адресу ниже.
Поле main
определяет точку входа приложения. Мы предоставляем его здесь для полноты. Однако точка входа важна только в том случае, если вы планируете опубликовать приложение в качестве пакета Node.js для других пользователей для скачивания и использования.
Поле dependencies
важное. Оно определяет пакеты Node.js, необходимые приложению. Вскоре вы подключаетесь к виртуальной машине во второй раз и выполните npm install
команду для установки этих пакетов.
В пакетах Node обычно используется схема Семантического версионирования. Номер версии состоит из трех компонентов: основной номер версии, дополнительный номер версии и номер исправления. Нотация тильды ~
здесь сообщает npm, что нужно установить последнюю версию исправлений для указанной основной и дополнительной версии. Ниже приведены последние версии, с помощью которых был протестирован этот модуль. На практике со временем можно увеличивать версию при обновлении и тестировании приложения, чтобы использовать новейшие функции, предоставляемые каждым зависимым пакетом.
Копирование файлов на виртуальную машину
Прежде чем продолжать, убедитесь, что у вас под рукой есть IP-адрес вашей виртуальной машины. Если у вас его нет, выполните приведенные ниже команды из Cloud Shell, чтобы получить IP-адрес.
ipaddress=$(az vm show \
--name MeanStack \
--resource-group "<rgn>[sandbox resource group name]</rgn>" \
--show-details \
--query [publicIps] \
--output tsv)
echo $ipaddress
Вы завершили редактирование файлов. Обязательно сохраните изменения в каждом файле и закройте редактор.
Чтобы закрыть редактор, выберите многоточие в правом верхнем углу, а затем нажмите кнопку "Закрыть редактор".
Выполните следующую
scp
команду, чтобы скопировать содержимое~/Books
каталога в сеансе Cloud Shell в то же имя каталога на виртуальной машине:scp -r ~/Books azureuser@$ipaddress:~/Books
Установка дополнительных пакетов узлов
Предположим, что во время процесса разработки вы определили больше пакетов Node, которые вы хотите использовать. Помните, что app/model.js
начинается со следующей строки.
var mongoose = require('mongoose');
Приложение использует Mongoose для передачи данных из базы данных MongoDB и в нее.
Приложению также требуются Express.js и пакеты body-parser. Body-parser — это подключаемый модуль, позволяющий Express работать с данными из веб-формы, отправленной клиентом.
Давайте подключимся к виртуальной машине и установим пакеты, указанные в package.json
.
Перед подключением к виртуальной машине убедитесь, что у вас есть IP-адрес виртуальной машины. Если у вас его нет, выполните команды Cloud Shell из предыдущего раздела, чтобы получить его.
Создайте подключение SSH к виртуальной машине, как и ранее:
ssh azureuser@$ipaddress
Перейдите
Books
в каталог под домашним каталогом:cd ~/Books
Запустите
npm install
, чтобы установить зависимые пакеты:sudo apt install npm -y && npm install
Не закрывайте подключение SSH для следующего раздела.
Тестирование приложения
Теперь вы готовы протестировать веб-приложение Node.js.
В каталоге
~/Books
выполните следующую команду, чтобы запустить веб-приложение:sudo nodejs server.js
Эта команда запускает приложение, ожидая входящие HTTP-запросы на порте 80.
В отдельной вкладке браузера перейдите по общедоступному IP-адресу виртуальной машины.
Откроется страница индексов с веб-формой.
Попробуйте добавить несколько книг в базу данных. Каждый раз при добавлении книги страница будет обновляться и показывать полный список книг.
Можно также нажать кнопку Удалить, чтобы удалить книгу из базы данных.