Advertisement
  1. Code
  2. Express

Erstellen Sie eine komplette MVC-Website mit ExpressJS

by
Difficulty:IntermediateLength:LongLanguages:

German (Deutsch) translation by Władysław Łucyszyn (you can also view the original English article)

In diesem Artikel erstellen wir eine komplette Website mit einer Front-zugewandten Client-Seite sowie einem Control Panel zur Verwaltung des Seiteninhalts. Wie Sie sich denken können, enthält die letzte Arbeitsversion der Anwendung viele verschiedene Dateien. Ich schrieb dieses Tutorial Schritt für Schritt und folgte dem Entwicklungsprozess, aber ich habe nicht jede einzelne Datei hinzugefügt, da dies ein sehr langes und langweiliges Lesen wäre. Der Quellcode ist jedoch auf GitHub verfügbar und ich empfehle dringend, dass Sie einen Blick darauf werfen.


Einführung

Express ist eines der besten Frameworks für Node. Es hat großartige Unterstützung und eine Reihe hilfreicher Funktionen. Es gibt eine Menge toller Artikel, die alle Grundlagen abdecken. Allerdings möchte ich dieses Mal ein wenig tiefer eintauchen und meinen Workflow für die Erstellung einer vollständigen Website teilen. Im Allgemeinen ist dieser Artikel nicht nur für Express, sondern auch für die Verwendung in Kombination mit anderen großartigen Tools, die für Node-Entwickler verfügbar sind.

Ich nehme an, dass Sie mit Nodejs vertraut sind, es auf Ihrem System installiert haben und dass Sie wahrscheinlich bereits einige Anwendungen damit erstellt haben.

Im Herzen von Express ist Connect. Dies ist ein Middleware-Framework, das mit vielen nützlichen Dingen ausgestattet ist. Wenn Sie sich fragen, was genau eine Middleware ist, hier ein kurzes Beispiel:

Middleware ist im Grunde eine Funktion, die request und response und eine next Funktion akzeptiert. Jede Middleware kann entscheiden, mit einem response objekt zu antworten oder den Fluss an die next Funktion weiterzuleiten, indem sie den nächsten Callback aufruft. Wenn Sie im obigen Beispiel den Aufruf der Methode next() in der zweiten Middleware entfernen, wird die Zeichenfolge hello world niemals an den Browser gesendet. Im Allgemeinen funktioniert Express so. Es gibt einige vordefinierte Middlewares, die Ihnen natürlich viel Zeit ersparen. Wie zum Beispiel der Body parser, der Anfragekörper analysiert und application / json, application / x-www-form-urlencoded und multipart / form-data unterstützt. Oder der Cookie parser, der Cookie-Header analysiert und req.cookies mit einem Objekt füllt, das mit dem Namen des Cookies verknüpft ist.

Express umschließt tatsächlich Connect und fügt einige neue Funktionen hinzu. Wie zum Beispiel Routing-Logik, die den Prozess viel reibungsloser macht. Hier ist ein Beispiel für die Behandlung einer GET-Anfrage:


Konfiguration

Es gibt zwei Möglichkeiten, Express einzurichten. Die erste ist, indem Sie es in Ihre package.json Datei und laufende npm install (es gibt einen Witz, der npm bedeutet kein Problem Mann :)).

Der Code des Frameworks wird in node_modules platziert und Sie können eine Instanz davon erstellen. Ich bevorzuge jedoch eine alternative Option, indem ich das Befehlszeilentool verwende. Installieren Sie Express einfach global mit npm install -g express. Dadurch haben Sie jetzt ein brandneues CLI-Instrument. Zum Beispiel, wenn Sie Folgendes ausführen:

Express erstellt ein Anwendungsskelett mit einigen bereits für Sie konfigurierten Dingen. Hier sind die Verwendungsoptionen für den Befehl express(1):

Wie Sie sehen können, gibt es nur ein paar Optionen, aber für mich sind sie genug. Normalerweise verwende ich less als CSS-Präprozessor und hogan als Template-Engine. In diesem Beispiel benötigen wir auch Sitzungsunterstützung, sodass das Argument --sessions dieses Problem löst. Wenn der obige Befehl abgeschlossen ist, sieht unser Projekt wie folgt aus:

Wenn Sie die Datei package.json auschecken, werden Sie sehen, dass alle Abhängigkeiten, die wir benötigen, hier hinzugefügt werden. Obwohl sie noch nicht installiert wurden. Um dies zu tun, führen Sie einfach npm install aus und dann wird der Ordner node_modules angezeigt.

Mir ist klar, dass der obige Ansatz nicht immer angemessen ist. Möglicherweise möchten Sie Ihre Route-Handler in einem anderen Verzeichnis oder etwas ähnliches platzieren. Aber wie Sie in den nächsten Kapiteln sehen werden, werde ich Änderungen an der bereits generierten Struktur vornehmen, was ziemlich einfach ist. Man sollte sich also den express(1) -Befehl als Boilerplatten-Generator vorstellen.


Schnelle Lieferung

Für dieses Tutorial entwarf ich eine einfache Website einer gefälschten Firma namens FastDelivery. Hier ist ein Screenshot des kompletten Designs:

site

Am Ende dieses Tutorials werden wir eine vollständige Webanwendung mit einem funktionierenden Control Panel haben. Die Idee besteht darin, jeden Teil der Website in separaten eingeschränkten Bereichen zu verwalten. Das Layout wurde in Photoshop erstellt und in CSS (weniger) und HTML (Hogan) -Dateien aufgeteilt. Jetzt werde ich den Schneideprozess nicht behandeln, weil es nicht das Thema dieses Artikels ist, aber wenn Sie irgendwelche Fragen diesbezüglich haben, zögern Sie nicht zu fragen. Nach dem Slicing haben wir folgende Dateien und App-Struktur:

Hier ist eine Liste der Elemente der Site, die wir verwalten werden:

  • Home (das Banner in der Mitte - Titel und Text)
  • Blog (Hinzufügen, Entfernen und Bearbeiten von Artikeln)
  • Seite Dienste
  • Karriereseite
  • Kontaktseite

Aufbau

Es gibt ein paar Dinge, die wir tun müssen, bevor wir mit der eigentlichen Implementierung beginnen können. Die Konfiguration ist eine davon. Stellen wir uns vor, dass unsere kleine Website an drei verschiedenen Orten bereitgestellt werden sollte - einem lokalen Server, einem Staging-Server und einem Produktionsserver. Natürlich sind die Einstellungen für jede Umgebung anders und wir sollten einen Mechanismus implementieren, der flexibel genug ist. Wie Sie wissen, wird jedes Knotenscript als Konsolenprogramm ausgeführt. So können wir problemlos Befehlszeilenargumente senden, die die aktuelle Umgebung definieren. Ich habe diesen Teil in ein separates Modul eingepackt, um später einen Test dafür zu schreiben. Hier ist die Datei /config/index.js:

Es gibt nur zwei Einstellungen (für jetzt) - mode und port. Wie Sie vielleicht vermuten, verwendet die Anwendung verschiedene Ports für die verschiedenen Server. Aus diesem Grund müssen wir den Einstiegspunkt der Website in app.js aktualisieren.

Um zwischen den Konfigurationen zu wechseln, fügen Sie einfach die Umgebung am Ende hinzu. Beispielsweise:

Wird herstellen:

Jetzt haben wir alle unsere Einstellungen an einem Ort und sie sind leicht zu verwalten.


Tests

Ich bin ein großer TDD-Fan. Ich werde versuchen, alle in diesem Artikel verwendeten Basisklassen abzudecken. Natürlich wird es zu lange dauern, Tests für absolut alles zu haben, aber im Allgemeinen sollten Sie so vorgehen, wenn Sie Ihre eigenen Apps erstellen. Eines meiner Lieblingsgerüste zum Testen ist jasmine. Natürlich ist es in der npm-Registrierung verfügbar:

Lassen Sie uns ein tests verzeichnis erstellen, das unsere Tests enthält. Das erste, was wir prüfen werden, ist unser Konfigurationssetup. Die Spezifikationsdateien müssen mit .spec.js enden, daher sollte die Datei config.spec.js heißen.

Führen Sie jasmine-node ./tests aus und du solltest folgendes sehen:

Diesmal schrieb ich die Implementierung zuerst und die Testsekunde. Das ist nicht genau der TDD-Weg, aber in den nächsten paar Kapiteln werde ich das Gegenteil tun.

Ich empfehle dringend, eine Menge Zeit damit zu verbringen, Tests zu schreiben. Es gibt nichts besseres als eine vollständig getestete Anwendung.

Vor ein paar Jahren habe ich etwas sehr Wichtiges erkannt, das dir helfen kann, bessere Programme zu produzieren. Jedes Mal, wenn Sie anfangen, eine neue Klasse, ein neues Modul oder nur eine neue Logik zu schreiben, fragen Sie sich:

Wie kann ich das testen?

Die Antwort auf diese Frage wird Ihnen helfen, viel effizienter zu programmieren, bessere APIs zu erstellen und alles in gut getrennte Blöcke zu setzen. Sie können keine Tests für Spaghetti-Code schreiben. Zum Beispiel in der Konfigurationsdatei oben (/config/index.js) Ich habe die Möglichkeit hinzugefügt, den mode im Konstruktor des Moduls zu senden. Sie fragen sich vielleicht, warum ich das mache, wenn die Hauptidee darin besteht, den Modus aus den Befehlszeilenargumenten zu bekommen? Es ist einfach ... weil ich es testen musste. Stellen wir uns vor, dass ich einen Monat später etwas in einer production konfiguration überprüfen muss, aber das Knotenscript wird mit einem staging-Parameter ausgeführt. Ohne diese kleine Verbesserung werde ich diese Veränderung nicht vornehmen können. Dieser letzte kleine Schritt verhindert nun tatsächlich Probleme in der Zukunft.


Datenbank

Da wir eine dynamische Website erstellen, benötigen wir eine Datenbank, in der wir unsere Daten speichern können. Ich habe mich für dieses Tutorial für mongodb entschieden. Mongo ist eine NoSQL-Dokumentendatenbank. Die Installationsanleitung kann hier gefunden werden und da ich ein Windows-Benutzer bin, habe ich stattdessen die Windows-Installation verfolgt. Wenn Sie mit der Installation fertig sind, führen Sie den MongoDB-Daemon aus, der standardmäßig Port 27017 überwacht. In der Theorie sollten wir in der Lage sein, eine Verbindung zu diesem Port herzustellen und mit dem mongodb-Server zu kommunizieren. Um dies von einem Node-Skript aus zu tun, benötigen wir einen mongodb-Modul / Treiber. Wenn Sie die Quelldateien für dieses Lernprogramm heruntergeladen haben, wurde das Modul bereits in der Datei package.json hinzugefügt. Wenn nicht, füge einfach "mongodb": "1.3.10" zu deinen Abhängigkeiten hinzu und führe npm install aus.

Als nächstes schreiben wir einen Test, der prüft, ob ein mongodb-Server läuft. /tests/mongodb.spec.js Datei:

Der Rückruf in der Methode .connect des Mongodb-Clients erhält ein db-Objekt. Wir werden es später verwenden, um unsere Daten zu verwalten, was bedeutet, dass wir innerhalb unserer Modelle darauf zugreifen müssen. Es ist keine gute Idee, jedes Mal ein neues MongoClient-Objekt zu erstellen, wenn wir eine Anfrage an die Datenbank stellen müssen. Deshalb habe ich den Aufruf des Express-Servers in den Callback der connect-Funktion verschoben:

Noch besser, da wir ein Konfigurations-Setup haben, wäre es eine gute Idee, den mongodb-Host und -Port dort zu platzieren und dann die Verbindungs-URL zu ändern auf:

Achten Sie genau auf die Middleware: attachDB, die ich kurz vor dem Aufruf der http.createServer-Funktion hinzugefügt habe. Dank dieser kleinen Ergänzung werden wir eine .db-Eigenschaft des Anforderungsobjekts auffüllen. Die gute Nachricht ist, dass wir während der Routendefinition mehrere Funktionen hinzufügen können. Beispielsweise:

Also ruft Express vorher attachDB an, um unseren Routen-Handler zu erreichen. Sobald dies geschieht, hat das Anfrageobjekt die Eigenschaft .db und wir können damit auf die Datenbank zugreifen.


MVC

Wir alle kennen das MVC-Muster. Die Frage ist, wie dies für Express gilt. Mehr oder weniger, es ist eine Frage der Interpretation. In den nächsten Kapiteln werde ich Module erstellen, die als Modell, Ansicht und Controller fungieren.

Model

Das Modell wird mit den Daten umgehen, die in unserer Anwendung enthalten sind. Es sollte Zugriff auf ein DB-Objekt haben, das von MongoClient zurückgegeben wird. Unser Modell sollte auch eine Methode haben, es zu erweitern, weil wir vielleicht verschiedene Arten von Modellen erstellen möchten. Zum Beispiel möchten wir vielleicht ein BlogModel oder ein ContactsModel. Daher müssen wir eine neue Spezifikation schreiben: /tests/base.model.spec.js, um diese beiden Modellfunktionen zu testen. Und denken Sie daran, dass wir durch die Definition dieser Funktionalitäten, bevor wir mit der Implementierung beginnen, garantieren können, dass unser Modul nur das macht, was wir wollen.

Anstelle eines realen DB-Objekts entschied ich, ein Mockup-Objekt zu übergeben. Das liegt daran, dass ich später etwas Spezifisches testen möchte, das von Informationen abhängt, die aus der Datenbank kommen. Es wird viel einfacher sein, diese Daten manuell zu definieren.

Die Implementierung der extend-Methode ist etwas knifflig, weil wir den Prototyp von module.exports ändern müssen, aber den ursprünglichen Konstruktor behalten müssen. Zum Glück haben wir schon einen schönen Test geschrieben, der beweist, dass unser Code funktioniert. Eine Version, die das obige übergibt, sieht so aus:

Hier gibt es zwei Hilfsmethoden. Ein Setter für das DB-Objekt und ein Getter für unsere Datenbank collection.

Aussicht

Die Ansicht zeigt Informationen auf dem Bildschirm an. Im Wesentlichen ist die Ansicht eine Klasse, die eine Antwort an den Browser sendet. Express bietet hierfür einen kurzen Weg:

Das Antwortobjekt ist ein Wrapper, der eine nette API hat, die unser Leben einfacher macht. Allerdings würde ich lieber ein Modul erstellen, das diese Funktionalität kapseln wird. Das Verzeichnis der Standardan views wird in templates geändert, und es wird ein neues erstellt, in dem die Base sichtklasse gehostet wird. Diese kleine Änderung erfordert jetzt eine weitere Änderung. Wir sollten Express mitteilen, dass sich unsere Vorlagendateien jetzt in einem anderen Verzeichnis befinden:

Zuerst definiere ich, was ich brauche, schreibe den Test und schreibe danach die Implementierung. Wir benötigen ein Modul, das den folgenden Regeln entspricht:

  • Sein Konstruktor sollte ein Antwortobjekt und einen Vorlagennamen erhalten.
  • Es sollte eine render methode haben, die ein Datenobjekt akzeptiert.
  • Es sollte erweiterbar sein.

Sie wundern sich vielleicht, warum ich die View-Klasse erweitere. Ist es nicht einfach die Methode response.render aufzurufen? In der Praxis gibt es Fälle, in denen Sie einen anderen Header senden oder das response objekt irgendwie manipulieren möchten. Wie zum Beispiel die Bereitstellung von JSON-Daten:

Anstatt dies jedes Mal zu tun, wäre es nett, eine HTMLView-Klasse und eine JSONView-Klasse zu haben. Oder sogar eine XMLView-Klasse zum Senden von XML-Daten an den Browser. Es ist einfach besser, wenn Sie eine große Website erstellen, solche Funktionalitäten zu integrieren, anstatt den gleichen Code immer wieder zu kopieren.

Hier ist die Spezifikation für die /views/Base.js:

Um das Rendering zu testen, musste ich ein Mockup erstellen. In diesem Fall habe ich ein Objekt erstellt, das das Antwortobjekt des Express nachahmt. Im zweiten Teil des Tests habe ich eine andere View-Klasse erstellt, die die Basisklasse erbt und eine benutzerdefinierte Rendermethode anwendet. Hier ist die Klasse /views/Base.js.

Jetzt haben wir drei Spezifikationen in unserem test verzeichnis und wenn Sie jasmine-node ./tests ausführen, sollte das Ergebnis sein:

Controller

Erinnerst du dich an die Routen und wie sie definiert wurden?

Das '/' nach der Route, das im obigen Beispiel der Controller ist. Es ist nur eine Middleware-Funktion, die request, response und next akzeptiert.

Oben sollte Ihr Controller im Kontext von Express aussehen. Das Befehlszeilentool express(1) erstellt ein Verzeichnis namens routes, aber in unserem Fall ist es besser, es als controllers zu bezeichnen, also habe ich es so geändert, dass es dieses Benennungsschema widerspiegelt.

Da wir nicht nur eine winzig kleine Anwendung erstellen, wäre es sinnvoll, wenn wir eine Basisklasse erstellen, die wir erweitern können. Wenn wir jemals irgendeine Art von Funktionalität an alle unsere Controller weitergeben müssen, wäre diese Basisklasse der perfekte Ort. Auch hier schreibe ich zuerst den Test, also definieren wir, was wir brauchen:

  • Es sollte über eine extend Methode verfügen, die ein Objekt akzeptiert und eine neue untergeordnete Instanz zurückgibt
  • Die untergeordnete Instanz sollte über eine run-Methode verfügen, bei der es sich um die alte Middleware-Funktion handelt
  • Es sollte eine name-Eigenschaft geben, die den Controller identifiziert
  • Wir sollten in der Lage sein, basierend auf der Klasse unabhängige Objekte zu erstellen

Also nur ein paar Dinge für den Moment, aber wir können später mehr Funktionalität hinzufügen. Der Test würde ungefähr so aussehen:

Und hier ist die Implementierung von /controllers/Base.js:

Natürlich sollte jede Kindklasse ihre eigene run methode zusammen mit ihrer eigenen Logik definieren.


FastDelivery Website

Ok, wir haben eine gute Auswahl an Klassen für unsere MVC-Architektur und haben unsere neu erstellten Module mit Tests abgedeckt. Jetzt sind wir bereit, mit unserer gefälschten Firma FastDelivery fortzufahren. Stellen wir uns vor, dass die Website aus zwei Teilen besteht - einem Frontend und einem Administrationsbereich. Das Front-End wird verwendet, um die Informationen, die in der Datenbank gespeichert sind, unseren Endbenutzern anzuzeigen. Das Admin-Panel wird verwendet, um diese Daten zu verwalten. Beginnen wir mit unserem Admin (Control) Panel.

Schalttafel

Lassen Sie uns zunächst einen einfachen Controller erstellen, der als Verwaltungsseite dient. /controllers/Admin.js Datei:

Durch Verwendung der vordefinierten Basisklassen für unsere Controller und Ansichten können wir problemlos den Einstiegspunkt für das Control Panel erstellen. Die View-Klasse akzeptiert den Namen einer Vorlagendatei. Gemäß dem obigen Code sollte die Datei admin.hjs heißen und in /templates abgelegt werden. Der Inhalt würde ungefähr so aussehen:

(Um dieses Tutorial relativ kurz und in einem leicht lesbaren Format zu halten, werde ich nicht jede einzelne Ansichtsvorlage zeigen. Ich empfehle dringend, dass Sie den Quellcode von GitHub herunterladen.)

Um den Controller sichtbar zu machen, müssen wir in app.js eine Route hinzufügen:

Beachten Sie, dass wir die Admin.run-Methode nicht direkt als Middleware senden. Das liegt daran, dass wir den Kontext beibehalten wollen. Wenn wir das tun:

Das Wort this im Admin weist auf etwas anderes hin.

Schutz des Administrationsbereichs

Jede Seite, die mit /admin beginnt, sollte geschützt sein. Um dies zu erreichen, verwenden wir Express Middleware: Sessions. Es verbindet einfach ein Objekt mit der Anfrage namens session. Wir sollten jetzt unseren Admin-Controller ändern, um zwei zusätzliche Dinge zu tun:

  • Es sollte prüfen, ob eine Sitzung verfügbar ist. Wenn nicht, dann zeigen Sie ein Login-Formular an.
  • Es sollte die Daten akzeptieren, die vom Login-Formular gesendet wurden, und den Benutzer autorisieren, wenn der Benutzername und das Passwort übereinstimmen.

Hier ist eine kleine Hilfsfunktion, die wir verwenden können, um dies zu erreichen:

Zuerst haben wir eine Anweisung, die versucht, den Benutzer über das Session-Objekt zu erkennen. Zweitens prüfen wir, ob ein Formular eingereicht wurde. Ist dies der Fall, sind die Daten aus dem Formular im request.body-Objekt verfügbar, das von der bodyParser-Middleware gefüllt wird. Dann überprüfen wir nur, ob der Benutzername und das Passwort übereinstimmen.

Und jetzt ist hier die run-Methode des Controllers, die unseren neuen Helfer verwendet. Wir prüfen, ob der Benutzer berechtigt ist, entweder das Bedienfeld selbst anzuzeigen, ansonsten zeigen wir die Anmeldeseite an:

Inhalt verwalten

Wie ich bereits am Anfang dieses Artikels erwähnt habe, haben wir viele Dinge zu verwalten. Um den Prozess zu vereinfachen, behalten wir alle Daten in einer Sammlung. Jeder Datensatz hat eine title-, text-, picture- und type genschaft. Die Eigenschaft type bestimmt den Eigentümer des Datensatzes. Beispielsweise benötigt die Seite "Kontakte" nur einen Datensatz mit dem type: 'contacts', während die Seite "Blog" mehr Datensätze benötigt. Wir brauchen also drei neue Seiten zum Hinzufügen, Bearbeiten und Anzeigen von Datensätzen. Bevor wir mit der Erstellung neuer Vorlagen, dem Styling und dem Einbringen neuer Dinge in den Controller beginnen, sollten wir unsere Modellklasse schreiben, die zwischen dem MongoDB-Server und unserer Anwendung steht und natürlich eine sinnvolle API bereitstellt.

Das Modell erstellt eine eindeutige ID für jeden Datensatz. Wir werden es brauchen, um die Informationen später zu aktualisieren.

Wenn wir einen neuen Datensatz für unsere Kontaktseite hinzufügen möchten, können wir einfach Folgendes verwenden:

Also, wir haben eine nette API, um die Daten in unserer Mongodb-Sammlung zu verwalten. Jetzt sind wir bereit, die Benutzeroberfläche für die Verwendung dieser Funktionalität zu schreiben. Für diesen Teil muss der Admin-Controller ziemlich geändert werden. Um die Aufgabe zu vereinfachen, habe ich beschlossen, die Liste der hinzugefügten Datensätze und das Formular zum Hinzufügen / Bearbeiten dieser zu kombinieren. Wie Sie auf dem folgenden Screenshot sehen können, ist der linke Teil der Seite für die Liste und der rechte Teil für das Formular reserviert.

control-panel

Alles auf einer Seite zu haben bedeutet, dass wir uns auf den Teil konzentrieren müssen, der die Seite rendert oder genauer gesagt auf die Daten, die wir an die Vorlage senden. Deshalb habe ich mehrere Hilfsfunktionen erstellt, die wie folgt kombiniert sind:

Es sieht ein bisschen hässlich aus, aber es funktioniert so, wie ich es wollte. Der erste Helfer ist eine del-Methode, die die aktuellen GET-Parameter überprüft und wenn sie action=delete&id=[id of the record] findet, entfernt sie Daten aus der Sammlung. Die zweite Funktion heißt form und ist hauptsächlich dafür zuständig, das Formular auf der rechten Seite der Seite anzuzeigen. Es prüft, ob das Formular übermittelt wird und aktualisiert oder erstellt Datensätze in der Datenbank. Am Ende holt die list methode die Information und erstellt eine HTML-Tabelle, die später an die Vorlage gesendet wird. Die Implementierung dieser drei Helfer finden Sie im Quellcode dieses Tutorials.

Hier habe ich beschlossen, Ihnen die Funktion zu zeigen, die den Datei-Upload übernimmt:

Wenn eine Datei gesendet wird, wird die Node-Skript .files genschaft des Anforderungsobjekts mit Daten gefüllt. In unserem Fall haben wir das folgende HTML-Element:

Dies bedeutet, dass wir über req.files.picture auf die übergebenen Daten zugreifen können. Im obigen Code-Snippet wird req.files.picture.path verwendet, um den rohen Inhalt der Datei zu erhalten. Später werden dieselben Daten in ein neu erstelltes Verzeichnis geschrieben und am Ende wird eine korrekte URL zurückgegeben. Alle diese Vorgänge sind synchron, aber es empfiehlt sich, die asynchrone Version von readFileSync, mkdirSync und writeFileSync zu verwenden.

Vorderes Ende

Die harte Arbeit ist jetzt abgeschlossen. Der Administrationsbereich funktioniert und wir verfügen über eine ContentModel-Klasse, die uns Zugriff auf die in der Datenbank gespeicherten Informationen gewährt. Jetzt müssen wir die Front-End-Controller schreiben und sie an den gespeicherten Inhalt binden.

Hier ist der Controller für die Homepage - /controllers/Home.js

Die Startseite benötigt einen Datensatz mit einem home typ und vier Datensätze mit einem blog typ. Sobald der Controller fertig ist, müssen wir nur eine Route hinzufügen in app.js:

Auch hier fügen wir das DB-Objekt an die request an. Ziemlich genau der gleiche Workflow wie im Administrationsbereich.

Die anderen Seiten für unser Front-End (Client-Seite) sind fast identisch, da sie alle einen Controller haben, der Daten unter Verwendung der Modellklasse und natürlich einer definierten Route abruft. Es gibt zwei interessante Situationen, die ich ausführlicher erläutern möchte. Der erste bezieht sich auf die Blog-Seite. Es sollte in der Lage sein, alle Artikel zu zeigen, aber auch nur einen zu präsentieren. Also müssen wir zwei Routen registrieren:

Sie verwenden beide den gleichen Controller: Blog, aber rufen Sie verschiedene run methoden auf. Achten Sie auf die Zeichenfolge /blog/:id. Diese Route entspricht URLs wie /blog/4e3455635b4a6f6dccfaa1e50ee71f1cde75222b und der lange Hash ist in req.params.id verfügbar. Mit anderen Worten, wir können dynamische Parameter definieren. In unserem Fall ist das die ID des Datensatzes. Sobald wir diese Informationen haben, können wir für jeden Artikel eine einzigartige Seite erstellen.

Der zweite interessante Teil ist, wie ich die Seiten Services, Karriere und Kontakte erstellt habe. Es ist klar, dass sie nur einen Datensatz aus der Datenbank verwenden. Wenn wir für jede Seite einen anderen Controller erstellen müssten, müssten wir denselben Code kopieren und einfügen und nur das type feld ändern. Es gibt jedoch einen besseren Weg, dies zu erreichen, indem Sie nur einen Controller haben, der den type in seiner run-Methode akzeptiert. Also hier sind die Routen:

Und der Controller würde so aussehen:


Einsatz

Die Bereitstellung einer Express-basierten Website entspricht der Bereitstellung einer anderen Node.js-Anwendung:

  • Die Dateien werden auf dem Server platziert.
  • Der Knotenprozess sollte gestoppt werden (wenn er ausgeführt wird).
  • Ein npm install ationsbefehl sollte ausgeführt werden, um die neuen Abhängigkeiten zu installieren (falls vorhanden).
  • Das Hauptskript sollte dann erneut ausgeführt werden.

Denken Sie daran, dass Node immer noch ziemlich jung ist, also kann nicht alles wie erwartet funktionieren, aber es werden ständig Verbesserungen vorgenommen. Zum Beispiel garantiert forever, dass Ihr Nodejs-Programm kontinuierlich ausgeführt wird. Sie können dies tun, indem Sie den folgenden Befehl ausführen:

Dies ist es, was ich auch auf meinen Servern verwende. Es ist ein nettes kleines Werkzeug, aber es löst ein großes Problem. Wenn Sie Ihre App nur mit dem Knoten yourapp.js ausführen, wird der Server nach dem unerwarteten Beenden des Skripts inaktiv. forever, startet einfach die Anwendung neu.

Now I'm not a system administrator, but I wanted to share my experience integrating node apps with Apache or Nginx, because I think that this is somehow part of the development workflow.

Wie Sie wissen, läuft Apache normalerweise auf Port 80, dh wenn Sie http://localhost oder http://localhost:80 öffnen, sehen Sie eine Seite, die von Ihrem Apache Server bedient wird und höchstwahrscheinlich Ihr Knotenscript auf a anderer Hafen. Sie müssen also einen virtuellen Host hinzufügen, der die Anforderungen akzeptiert und an den richtigen Port sendet. Angenommen, ich möchte die Website, die wir gerade erstellt haben, auf meinem lokalen Apache-Server unter der Adresse expresscompletewebsite.dev hosten. Als erstes müssen wir Ihre Domain zur hosts-Datei hinzufügen.

Danach müssen wir die httpd-vhosts.conf-Datei im Apache-Konfigurationsverzeichnis bearbeiten und hinzufügen

Der Server akzeptiert weiterhin Anforderungen an Port 80, leitet sie jedoch an Port 3000 weiter, wo der Knoten abhört.

Das Nginx-Setup ist viel einfacher und um ehrlich zu sein, ist es eine bessere Wahl für das Hosting von Nodejs-basierten Apps. Sie müssen den Domänennamen in Ihrer hosts-Datei noch hinzufügen. Erstellen Sie danach einfach eine neue Datei im Verzeichnis /sites-enabled unter der Nginx-Installation. Der Inhalt der Datei würde ungefähr so aussehen:

Beachten Sie, dass Sie sowohl Apache als auch Nginx nicht mit dem obigen Host-Setup ausführen können. Das liegt daran, dass beide Port 80 benötigen. Außerdem sollten Sie ein wenig Nachforschungen über eine bessere Serverkonfiguration anstellen, wenn Sie die obigen Code-Snippets in einer Produktionsumgebung verwenden möchten. Wie gesagt, ich bin kein Experte auf diesem Gebiet.


Fazit

Express ist ein großartiger Rahmen, der Ihnen einen guten Ausgangspunkt bietet, um mit dem Erstellen Ihrer Anwendungen zu beginnen. Wie Sie sehen können, ist es eine Frage der Wahl, wie Sie es erweitern und was Sie verwenden werden, um damit zu bauen. Es vereinfacht die langweiligen Aufgaben, indem es ein paar großartige Middlewares benutzt und die spaßigen Teile dem Entwickler überlässt.

Quellcode

Der Quellcode für diese von uns erstellte Beispielwebsite ist auf GitHub verfügbar - https://github.com/tutsplus/build-complete-website-expressjs. Fühlen Sie sich frei, es auszuspannen und damit zu spielen. Hier sind die Schritte zum Ausführen der Site.

  • Laden Sie den Quellcode herunter
  • Gehe zum app-Verzeichnis
  • Führen Sie npm install aus
  • Führen Sie den mongodb-Daemon aus
  • Führen Sie den node app.js aus
Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.