Zeitgemäße Webanwendungen in JavaScript entwickeln
Seite 2: Einrichten und benutzen
Bevor es losgehen kann
Um Node.js überhaupt ausführen zu können, stehen prinzipiell zwei Möglichkeiten zur Verfügung: Zum einen lässt es sich, wie zumindest unter Linux üblich, aus dem Quelltext übersetzen. Zum anderen kann ein auf das jeweilige Betriebssystem angepasstes vorgefertigtes Installationspaket verwendet werden. Auf der Webseite von Node.js finden sich mittlerweile Pakete für Mac OS X und Windows, für Linux stehen vorübersetzte Binärpakete zur Verfügung.
Nach der Installation von Node.js besteht der einfachste Weg zu überprüfen, ob die Installation erfolgreich war, darin, die Anwendung node über eine Konsole aufzurufen:
$ node
Erscheint daraufhin ein >-Zeichen als Eingabeaufforderung, hat es funktioniert. Nun ist die Eingabe von JavaScript-Anweisungen möglich, die direkt übersetzt und ausgeführt werden.
Um Node.js wieder zu beenden, genügt ein Tastendruck auf Strg + C. Um sicherzustellen, dass diese Tastenkombination nicht versehentlich eingegeben wurde und die aktive Sitzung damit unbeabsichtigt beendet, erfolgt eine zweite Eingabeaufforderung.
Hallo HTTP-Welt!
Um die Fähigkeiten von Node.js über die Grundlagen von JavaScript hinaus zu erweitern, lassen sich Module ergänzen. Neben der Möglichkeit, diese aus dem Web herunterzuladen und nachträglich zu installieren, enthält schon die Standardinstallation einige integrierte Komponenten.
Das für die Webentwicklung wichtigste ist das http-Modul, das Funktionen zum Implementieren von Webservern und -clients enthält. Um es verwenden zu können, ist es zunächst mit der require-Funktion in die eigene Anwendung zu importieren:
var http = require('http');
Die Zuweisung an die Variable http ermöglicht dabei den späteren Zugriff auf das Modul, um beispielsweise dessen Objekte und Funktionen verwenden zu können.
Das Modul http enthält die Funktion createServer, mit deren Hilfe sich ein HTTP-Server erzeugen lässt. Dieser Funktion wird eine weitere als Callback übergeben, die für die Verarbeitung von eingehenden HTTP-Anfragen und deren Beantwortung zuständig ist. Der Zugriff auf die zugrunde liegenden Anfrage und die dazugehörige Antwort erfolgt dabei über die beiden Parameter req und res:
var server = http.createServer(function (req, res) {
// ...
});
Analog zur Konsolen- soll auch die Webanwendung zunächst den Text Hallo Welt! zurückgeben. Als Zeichen, dass die Verarbeitung der Anfrage erfolgreich war, werden zudem der HTTP-Statuscode 200 gesendet und der MIME-Type der Antwort auf text/plain gesetzt.
Beides erfolgt mit einem Aufruf der Funktion writeHead des Objekts res, wobei sich zusätzlich zum MIME-Type auch beliebige andere Header-Informationen senden lassen, indem sie dem Parameterobjekt hinzugefügt werden:
res.writeHead(200, {
'content-type': 'text/plain'
});
Um die eigentliche Ausgabe vorzunehmen, dient die Funktion write. Nach dem Senden ist die Antwort des Webservers mit der Funktion end abzuschließen .
res.write('Hallo Welt!\n');
res.end();
Zur Ausführung muss der Webserver noch an einen Port gebunden werden, der dafür an die Funktion listen übergeben wird.
server.listen(3000);
Alternativ lässt sich diese Funktion, im Sinne eines flüssigeren Schreibstils, auch direkt nach dem Aufruf von createServer aufrufen:
http.createServer(function (req, res) {
// ...
}).listen(3000);
Nachdem der gesamte Code in eine Datei, in diesem Beispiel app.js, gespeichert wurde, ist der Webserver aufrufbereit:
$ node app.js
Module, Module, Module
Obwohl Node.js bereits einige Module enthält, gibt es zahlreiche Anwendungsfälle, die davon nicht abgedeckt sind. Dazu zählen beispielsweise das Internationalisieren und Lokalisieren von Anwendungen, der Zugriff auf Datenbanken oder das Debuggen mit einer grafischen Benutzeroberfläche.
Für viele dieser Belange existieren Implementierungen, die die Entwickler der Community in der Regel kostenfrei zur Verfügung stellen. Für die Integration der Module in eigene Anwendungen, und zur Verwaltung der Abhängigkeiten zwischen ihnen dient der Node.js Package Manager (npm). Seit Node.js 0.6.3 entfällt die gesonderte Installation von npm, da er bereits in der Standardinstallation enthalten ist.
Um ein Modul zu installieren, ist npm außer dem Parameter install auch dessen Name zu übergeben:
$ npm install node-force-domain
node-force-domain@0.0.4 ./node_modules/node-force-domain
Soll nicht die aktuelle, sondern eine vorherige Version einer Komponente installiert werden, lässt sich die Versionsnummer bei der Installation gezielt angeben:
$ npm install node-force-domain@0.0.3
node-force-domain@0.0.3 ./node_modules/node-force-domain
Bei erfolgreicher Installation meldet npm die Version des installierten Moduls und den zugehörigen Pfad. In beiden Fällen steht es der Anwendung danach zur Verfügung und lässt sich mit der require-Funktion importieren:
var forceDomain = require('node-force-domain');
Sofern ein Modul von weiteren abhängt, löst npm diese Abhängigkeiten automatisch auf und installiert auch die anderen, wobei er diese in einem speziellen Unterordner ablegt. Das stellt sicher, dass verschiedene Module von unterschiedlichen Versionen ein- und desselben Moduls abhängen können, ohne dass es zu Versionskonflikten kommt.
Und Sie gehören zu ...?
Sollen die Abhängigkeiten einer Anwendung festgeschrieben werden, lässt sich zu diesem Zweck package.json verwenden. npm kann damit sämtliche Abhängigkeiten automatisch auflösen.
Dazu ist zunächst eine Datei package.json zu erzeugen und im Wurzelverzeichnis der Anwendung zu hinterlegen. Prinzipiell muss sie mindestens zwei Elemente enthalten: den Namen der Anwendung und deren Versionsnummer. Beide Angaben sind zwingend erforderlich:
{
"name": "myapp",
"version": "0.0.1"
}
Um nun die Abhängigkeiten einer Anwendung zu anderen Modulen anzugeben, ist package.json um eine Eigenschaft dependencies zu ergänzen, wobei deren Wert einem Objekt entspricht, das die folgenden Beziehungen definiert:
{
"name": "myapp",
"version": "0.0.1",
"dependencies": {
"node-force-domain": "0.0.4"
}
}
Nach der Definition der Zusammenhänge einer Anwendung in der Datei package.json kann npm diese automatisch auflösen. Deshalb ist es nicht erforderlich, das node_modules-Verzeichnis in die Versionsverwaltung einzubinden. Stattdessen genügt es, die eigentliche Anwendung und die Datei package.json zu speichern. Sämtliche Abhängigkeiten lassen sich nun durch Aufrufen von npm mit dem Parameter install ohne Angabe eines Moduls analysieren und auflösen:
$ npm install
node-force-domain@0.0.4 ./node_modules/node-force-domain