Övning – Skapa en grundläggande webbapp
Hittills har du MongoDB och Node.js installerat på den virtuella Ubuntu-datorn (VM). Nu är det dags att skapa ett enkelt webbprogram för att se hur allt fungerar i praktiken. Längs vägen ser du hur AngularJS och Express passar in.
Ett bra sätt att lära sig är genom att följa exempel. Webbprogrammet som du skapar implementerar en grundläggande bokdatabas. Med webbprogrammet kan du lista information om böcker, lägga till nya böcker och ta bort befintliga böcker.
Webbprogrammet som du ser här visar många begrepp som gäller för de flesta MEAN-stackwebbprogram. Baserat på dina behov och intressen kan du utforska de funktioner som du behöver för att skapa dina egna MEAN-stackprogram.
Så här ser webbprogrammet Böcker ut.
Så här fungerar de olika komponenterna i MEAN-stacken.
- MongoDB lagrar information om böcker.
- Express.js dirigerar varje HTTP-begäran till lämplig hanterare.
- AngularJS ansluter användargränssnittet till programmets affärslogik.
- Node.js är värd för programmet på serversidan.
Viktigt!
I utbildningssyfte ska du här skapa ett enkelt webbprogram. Målet är att du ska testa MEAN-stacken för att få en uppfattning om hur den fungerar. Programmet är inte tillräckligt säkert eller redo för produktionsanvändning.
Och Express?
Hittills har du installerat MongoDB och Node.js på den virtuella datorn. Hur är det med Express.js, E i MEAN-förkortningen?
Express.js är ett webbserverramverk som skapats för Node.js som förenklar processen för att skapa webbprogram.
Det huvudsakliga syftet med Express är att hantera routning av begäranden.
Routning syftar på hur programmet svarar på en begäran till en viss slutpunkt. En slutpunkt består av en sökväg eller URI och en begärandemetod som GET eller POST. Du kanske exempelvis svarar på en GET-begäran till slutpunkten /book
genom att tillhandahålla en lista över alla böcker i databasen. Du kan svara på en POST-begäran till slutpunkten genom att /book
lägga till en post i databasen baserat på fält som användaren angav i ett webbformulär.
I webbprogrammet som du snart skapar använder du Express för att dirigera HTTP-begäranden och för att returnera webbinnehåll till användaren. Express kan också hjälpa dina webbprogram att arbeta med HTTP-cookies och bearbeta frågesträngar.
Express är ett Node.js-paket. Du använder verktyget npm, som medföljer Node.js, för att installera och hantera Node.js-paket. Senare i den här lektionen skapar du en fil med namnet package.json
för att definiera Express och andra beroenden och kör npm install
sedan kommandot för att installera dessa beroenden.
Och AngularJS?
Precis som Express är AngularJS, A i MEAN-förkortningen, inte installerat ännu.
AngularJS gör webbprogram enklare att skriva och testa eftersom det gör att du bättre kan skilja utseendet på din webbsida – HTML-koden – från hur webbsidan fungerar. Om du är bekant med MVC-mönstret (model-view-controller) eller begreppet databindning bör AngularJS vara bekant för dig.
AngularJS är ett JavaScript-ramverk på klientsidan , vilket innebär att det bara behöver vara tillgängligt på klienten som har åtkomst till programmet. Det betyder att AngularJS körs i användarens webbläsare, inte på din webbserver. Och eftersom AngularJS är JavaScript kan du använda det för att enkelt hämta data från webbservern som ska visas på sidan.
Du installerar egentligen inte AngularJS. I stället lägger du till en referens till JavaScript-filen på HTML-sidan, precis som med andra JavaScript-bibliotek. Du kan lägga till AngularJS till dina webbsidor på flera sätt. Här läser du in AngularJS från ett nätverk för innehållsleverans (CDN). Ett CDN är ett sätt att distribuera bilder, videoklipp och annat innehåll geografiskt för att förbättra hämtningshastigheten.
Lägg inte till den här koden ännu, men här är ett exempel som läser in AngularJS från ett CDN. Du lägger vanligtvis till den här koden i <head>
avsnittet på HTML-sidan.
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.2/angular.min.js"></script>
Kommentar
Blanda inte ihop AngularJS med Angular. Många av begreppen i AngularJS och Angular påminner om varandra, men AngularJS är föregångaren till Angular. AngularJS används fortfarande ofta för att skapa webbprogram. Medan AngularJS baseras på JavaScript, bygger Angular på TypeScript, ett programmeringsspråk som gör det enklare att skriva JavaScript-program.
Hur gör jag för att skapa programmet?
Här använder du en grundläggande process. Du skriver programkod från Cloud Shell och använder sedan secure copy protocol (SCP) för att kopiera filerna till den virtuella datorn. Sedan startar du programmet Node.js och ser resultatet i webbläsaren.
I praktiken skriver och testar du vanligtvis webbprogrammet i en mer lokal miljö, till exempel från din bärbara dator eller från en virtuell dator som du kör lokalt. Du kan lagra koden i ett versionskontrollsystem, till exempel Git. Använd sedan ett SYSTEM för kontinuerlig integrering och kontinuerlig leverans (CI/CD), till exempel Azure DevOps, för att testa dina ändringar och ladda upp dem till den virtuella datorn. Vi pekar på fler resurser i slutet av den här modulen.
Skapa webbprogrammet Books
Här skapar du alla kod-, skript- och HTML-filer som utgör ditt webbprogram. För korthet markerar vi de viktiga delarna i varje fil men går inte in på fullständig information.
Om du fortfarande är ansluten till den virtuella datorn via SSH kör du exit
för att lämna SSH-sessionen och återgå till Cloud Shell.
exit
Nu är du tillbaka i Cloud Shell-sessionen.
Skapa filerna
Från Cloud Shell kör du dessa kommandon för att skapa mappar och filer för ditt webbprogram:
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
Webbprogrammet innehåller följande mappar och filer:
-
Books
är projektets rotkatalog.-
server.js
definierar startpunkten till webbprogrammet. Den läser in de nödvändiga Node.js-paketen, anger lyssningsporten och börjar lyssna efter inkommande HTTP-trafik. -
package.json
innehåller information om ditt program, inklusive namn, beskrivning och vilka Node.js-paket programmet ska köra.
-
-
Books/app
innehåller kod som körs på servern.-
model.js
definierar databasanslutningen och schemat. Du kan se det som datamodellen för ditt program. -
routes.js
hanterar routning av begäranden. Den definierar exempelvis GET-begäranden till/book
-slutpunkten genom att tillhandahålla en lista över alla böcker i databasen.
-
-
Books/public
innehåller filer som hämtas direkt till klientens webbläsare.-
index.html
innehåller indexsidan. Den innehåller ett webbformulär som gör att användaren kan skicka information om böcker. Den visar också alla böcker i databasen och gör att du kan ta bort poster från databasen. -
script.js
innehåller JavaScript-kod som körs i användarens webbläsare. Den kan skicka begäranden till servern för att visa en lista över böcker, lägga till böcker i databasen och ta bort böcker från databasen.
-
-
Kör kommandot
code
för att öppna dina filer via Cloud Shell-redigeraren.code Books
Skapa datamodellen
Öppna och lägg till följande kod från redigeraren
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;
Viktigt!
När du klistrar in eller ändrar koden i en fil i redigeringsprogrammet, är det viktigt att du sparar efteråt via menyn ”...” eller med snabbtangenten (Ctrl+S i Windows och Linux eller Cmd+S i macOS).
I den här koden används Mongoose för att förenkla dataöverföringen till och från MongoDB. Mongoose är ett schemabaserat system för modellering av data. Koden definierar ett databasdokument med namnet ”Book” med det angivna schemat. Schemat definierar fyra fält som beskriver en enskild bok:
- Bokens namn eller titel
- Dess internationella standardboknummer (ISBN) som unikt identifierar boken
- Bokens författare
- Antalet sidor som den innehåller
Sedan skapar du HTTP-hanterare som mappar GET-, POST- och DELETE-begäranden till databasåtgärder.
Skapa de Express.js vägar som hanterar HTTP-begäranden
Öppna och lägg till följande kod från redigeraren
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;
Den här koden skapar fyra vägar för programmet. Här är en kort översikt över var och en.
HTTP-verb Slutpunkt beskrivning GET /book
Hämtar alla böcker från databasen. POST /book
Skapar ett Book
-objekt baserat på de fält som användaren har angett i webbformuläret och skriver objektet till databasen.DELETE /book/:isbn
Tar bort en bok, baserat på dess ISBN, från databasen. GET *
Returnerar indexsidan när ingen annan väg matchas. Express.js kan hantera HTTP-svar direkt i routningshanteringskoden, eller så kan det hantera statiskt innehåll från filer. Den här koden visar båda metoderna. De första tre vägarna returnerar JSON-data för API-förfrågningar om böcker. Den fjärde vägen (standardfallet) returnerar innehållet i indexfilen
index.html
.
Skapa JavaScript-programmet för klientsidan
Öppna
public/script.js
från redigeraren och lägg till den här koden: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); }); }; });
Observera hur den här koden definierar en modul med namnet
myApp
och en kontrollant med namnetmyCtrl
. Vi kommer inte att gå in i detalj på hur modulen och kontrollanten fungerar här, men du ska använda dessa namn i nästa steg för att binda användargränssnittet (HTML-kod) till programmets affärslogik.Tidigare skapade du fyra vägar som hanterar olika GET-, POST- och DELETE-åtgärder på servern. Den här koden liknar dessa åtgärder, men från klientsidan (användarens webbläsare).
Funktionen
getData
skickar exempelvis en GET-begäran till slutpunkten/book
. Kom ihåg att servern hanterar den här begäran genom att hämta information om alla böcker från databasen och returnera den informationen som JSON-data i svaret. Observera hur JSON-data i svaret tilldelas till variabeln$scope.books
. Du får lära dig hur den här koden påverkar vad användaren ser på webbsidan i nästa steg.Den här koden anropar funktionen
getData
när sidan läses in. Du kan utforska funktionernadel_book
ochadd_book
för att få en uppfattning om hur de fungerar. Du behöver inte kod på klientsidan för att matcha serverns standardhanterare, eftersom standardhanteraren returnerar indexsidan och inte JSON-data.
Skapa användargränssnittet
Öppna
public/index.html
från redigeraren och lägg till den här koden:<!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>
Den här koden skapar ett grundläggande HTML-formulär med fyra fält för att skicka bokdata och en tabell som visar alla böcker som lagras i databasen.
Även om HTML-koden är standard kan HTML-attributen
ng-
vara obekanta för dig. Dessa HTML-attribut kopplar AngularJS-koden till användargränssnittet. När du till exempel väljer Lägg till anropar AngularJS funktionenadd_book
, som skickar formulärets data till servern.Du kan undersöka koden här för att få en uppfattning om hur vart och ett av attributen
ng-
relaterar till programmets affärslogik.
Skapa Express.js-servern som värd för programmet
Öppna
server.js
från redigeraren och lägg till den här koden: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')); });
Den här koden skapar själva webbprogrammet. Den hanterar statiska filer från
public
katalogen och använder de vägar som du definierade tidigare för att hantera begäranden.
Definiera paketinformation och beroenden
Som du kanske minns innehåller package.json
information om ditt program, inklusive namn, beskrivning och vilka Node.js-paket programmet ska köra.
Öppna
package.json
från redigeraren och lägg till den här koden:{ "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" } }
Du ser information, eller metadata, om ditt program, inklusive dess namn, beskrivning och licens.
Fältet repository
anger var koden finns. Om det behövs kan du granska koden senare på GitHub på URL:en som visas här.
Fältet main
definierar programmets startpunkt. Vi tillhandahåller den här för fullständighet. Startpunkten är dock bara viktig om du planerar att publicera ditt program som ett Node.js paket som andra kan ladda ned och använda.
Fältet dependencies
är viktigt. Det definierar Node.js-paketen som ditt program behöver. Snart ansluter du till den virtuella datorn en andra gång och kör npm install
kommandot för att installera dessa paket.
Node-paket använder vanligtvis det semantiska versionshanteringsschemat. Versionsnumret innehåller tre komponenter: högre version, lägre version och uppdatering.
~
-notationen (tilde) här beordrar npm att installera den senaste uppdateringsversionen under de angivna högre och lägre versionerna. De versioner som du ser här är de senaste som den här modulen testades med. I praktiken kan du öka versionen med tiden allteftersom du uppdaterar och testar ditt program med de senaste funktionerna som varje beroende paket tillhandahåller.
Kopiera filerna till den virtuella datorn
Innan du fortsätter kontrollerar du att du har den virtuella datorns IP-adress till hands. Om du inte har det kör du dessa kommandon från Cloud Shell för att hämta det:
ipaddress=$(az vm show \
--name MeanStack \
--resource-group "<rgn>[sandbox resource group name]</rgn>" \
--show-details \
--query [publicIps] \
--output tsv)
echo $ipaddress
Nu är du klar med redigeringen av filerna. Kontrollera att du har sparat ändringarna i varje fil och stäng sedan redigeraren.
Om du vill stänga redigeraren väljer du ellipserna i det övre högra hörnet och väljer sedan Stäng redigeraren.
Kör följande
scp
kommando för att kopiera innehållet~/Books
i katalogen i Cloud Shell-sessionen till samma katalognamn på den virtuella datorn:scp -r ~/Books azureuser@$ipaddress:~/Books
Installera fler Node-paket
Anta att du under utvecklingsprocessen identifierade fler Node-paket som du vill använda. Som du kanske minns börjar exempelvis app/model.js
med den här raden.
var mongoose = require('mongoose');
Som vi nämnde tidigare använder programmet Mongoose för att överföra data till och från MongoDB-databasen.
Programmet kräver också Express.js och body-parser-paketen. Body-parser är ett plugin-program som gör att Express kan arbeta med data från webbformuläret som skickas av klienten.
Nu ska vi ansluta till den virtuella datorn och installera de paket som du angav i package.json
.
Innan du ansluter till den virtuella datorn kontrollerar du att du har den virtuella datorns IP-adress till hands. Om du inte har det kör du Cloud Shell-kommandona i föregående avsnitt för att hämta det.
Skapa en SSH-anslutning till den virtuella datorn, som du gjorde tidigare:
ssh azureuser@$ipaddress
Flytta till
Books
katalogen under hemkatalogen:cd ~/Books
Kör
npm install
för att installera de beroende paketen:sudo apt install npm -y && npm install
Håll SSH-anslutningen öppen för nästa avsnitt.
Testa programmet
Nu är det dags att testa Node.js-webbprogrammet!
Kör det här kommandot från
~/Books
katalogen för att starta webbprogrammet:sudo nodejs server.js
Det här kommandot startar programmet genom att lyssna efter inkommande HTTP-begäranden på port 80.
Gå till den virtuella datorns offentliga IP-adress från en separat webbläsarflik.
Du ser indexsidan, som innehåller ett webbformulär.
Prova att lägga till några böcker till databasen. Varje gång du lägger till en bok uppdateras den fullständiga listan med böcker på sidan.
Du kan även välja Ta bort om du vill ta bort en bok från databasen.