node.js

Wir bieten auf unseren System auch node.js als serverbasierten JavaScript-Interpreter an. Mit node.js lassen sich serverbasierte Dienste entwickeln, d.h. die darunter laufenden Scripts binden sich typischerweise an einen Netzwerkport, statt wie andere Programmiersprachen unter CGI oder FastCGI zu laufen. Das macht ihre Einbindung etwas schwieriger, aber natürlich ist auch das bei Uberspace.de kein Problem.

Versionen

Je nachdem auf welchem Host du dich befindest, stehen dir möglicherweise mehrere node.js-Versionen zur Verfügung, da wir bei Updates die vorherigen Versionen parallel dazu immer noch installiert lassen. Welche Version die Standardversion ist, erfährst du durch Eingabe von node -v:

[mareike@neon ~]$ node -v
v0.6.15

Wenn auf deinem Host mehrere node.js-Versionen verfügbar sind und du nicht die Standardversion verwenden willst, kannst du eine von zwei Möglichkeiten nutzen:

Version via Programmname wählen

Gibst du auf der Shell node- ein und drückst zweimal TAB, so werden dir alle verfügbaren Versionen angezeigt. Du kannst node.js dann einfach mit der gewünschten Version im Namen aufrufen:

[mareike@neon ~]$ node-0.6 -v
v0.6.0
[mareike@neon ~]$ node-0.6.5 -v
v0.6.5
[mareike@neon ~]$ node-0.6.15 -v
v0.6.15

Version via PATH wählen

Möchtest du eine bestimmte node-Version als Standard verwenden, kannst du die Umgebungsvariable PATH über eine Zeile in deiner .bash_profile anpassen, um jene zu aktivieren; der source-Aufruf stellt sicher, dass die neue Version auch direkt in deiner laufenden Shell zur Anwendung kommt (hier im Beispiel für node.js 0.6.15):

[mareike@neon ~] echo 'export PATH=/package/host/localhost/nodejs-0.6.15/bin:$PATH' >> ~/.bash_profile
[mareike@neon ~] source ~/.bash_profile

Zur Kontrolle kannst du einmal node -v aufrufen, was nun die Version 0.6.15 ergeben sollte:

[mareike@neon ~]$ node -v
v0.6.15

Beispiel

Um das Beispielscript aus der offiziellen Dokumentation zu zitieren:

var http = require('http');
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n');
}).listen(8124, "127.0.0.1");
console.log('Server running at http://127.0.0.1:8124/');

(Wenn du das Beispiel reproduzieren möchtest, wähle bitte irgeneinen anderen hohen Port > 1024 statt des Ports 8124 im Beispiel. Jeder Port kann nur einmal belegt werden, und nach derzeitigem Kenntnisstand gibt es auf allen Hosts schon jemanden, der diesen Port benutzt - also einfach einen anderen nehmen!)

Testweise kannst du das Script wie vorgeschlagen als example.js in deinem Uberspace ablegen. Es muss hierbei ausdrücklich nicht im DocumentRoot liegen, denn der Apache-Webserver wird die HTTP-Requests sowieso einfach nur an deinen mit node.js realisierten Serverdienst durchreichen und nicht selbst die fraglichen Dateien lesen. Du kannst es also zum Beispiel direkt in deinem Home-Verzeichnis ablegen; für produktive Projekte würde es sich anbieten, einen eigenen Ordner dafür anzulegen.

Einrichtung als Dienst

Damit der Serverdienst gestartet wird und auch noch weiterlaufen kann, nachdem du dich bereits wieder ausgeloggt hast, kannst du ihn am einfachsten unter den daemontools laufen lassen, die nicht nur für den automatischen Start nach einem Reboot des Servers sorgen, sondern deine Applikation auch automatisch neu starten, sollte sie aus irgendeinem Grund mal crashen. Solltest du noch kein eigenes ~/service-Verzeichnis haben, kannst du dir flugs eins anlegen:

[mareike@neon ~] uberspace-setup-svscan

Wenige Sekunden später ist dein ~/service-Verzeichnis einsatzbereit. Jetzt ist deine Applikation an der Reihe - so geht's:

[mareike@neon ~] uberspace-setup-service exampleservice node ~/example.js

Damit wird automatisch ein Dienst namens exampleservice in deinem ~/service-Verzeichnis angelegt, der deine node.js-Applikation startet. Du kannst ihn wie jeden anderen Dienst auch beliebig steuern.

Brücke zum Webserver

Was nun noch fehlt, ist die Brücke zum Webserver zu deinem Dienst. Das lässt sich am einfachsten mit einer .htaccess-Datei regeln. Legen wir als Beispiel eine einfache .htaccess-Datei im DocumentRoot an:

[mareike@neon html]$ cat .htaccess
RewriteEngine On
RewriteRule ^nodejs/(.*) http://localhost:8124/$1 [P]

Jetzt werden sämtliche Aufrufe von - in diesem Beispiel - https://mareike.neon.uberspace.de/nodejs/… durch den Apache via Proxy an deinen node.js-Dienst durchgeleitet. Das war's!

(Bitte beachte den “/“ hinter dem Pfad in der URL - ohne den matcht die RewriteRule nicht, so dass der Request dann nicht durchgereicht wird.)

WebSockets

Es gibt einen Punkt, an dem die Proxy-RewriteRule aus dem vorherigen Abschnitt nicht funktioniert, nämlich dann, wenn zusätzlich zur normalen HTTP-Kommunikation auch WebSockets zum Einsatz kommen. Auch wenn es im ersten Moment so aussieht, als wären WebSockets auch „irgendwie HTTP“, so benutzen sie lediglich HTTP mit einem zusätzlichen Header als Handshake, führen danach aber Kommunikation, die nichts mehr mit HTTP zu tun hat und die in aller Regel auch nicht durch einen Proxy kommen.

In diesem Fall hilft nur eine Möglichkeit: Teile uns den Port, auf dem deine Applikation läuft, an hallo@uberspace.de mit, und wir schalten ihn in unserer Firewall für dich frei. Auf diese Weise kannst du dann vom Browser aus direkt (unter Umgehung des Apache-Webservers) mit deiner Node-Instanz kommunizieren - und so funktionieren WebSockets dann auch.

npm

npm ist der „Node Package Manager“. Er ermöglicht die einfache Installation von zusätzlichen Modulen für node.js. Um ihn nutzen zu können, solltest du eine eigene .npmrc anlegen, die wie folgt aussieht:

[mareike@neon ~]$ cat > ~/.npmrc <<__EOF__
prefix = $HOME
umask = 077
__EOF__

Der angegebene prefix ist das Basisverzeichnis, wenn du mit npm -g Module global installieren willst. Die zweite Zeile sorgt dafür, dass npm alle Dateien und Verzeichnisse nur für dich selbst les- und schreibbar anlegt. Das ist wichtig, damit npm, wenn du ein npm install … irrtümlich direkt in deinem Home-Verzeichnis (und nicht im Verzeichnis deiner Applikation) ausführst, nicht dein Home-Verzeichnis mit einem ''chmod 755'' behandelt und es somit für andere lesbar macht.

node.js < 0.6.5

Bitte führe das „One Line Install“ von der npm-Website aus:

[mareike@neon ~]$ curl http://npmjs.org/install.sh | clean=no sh

Wie du siehst, haben wir hier ein clean=no ergänzt. npm 1.x versucht bei Installation nämlich automatisch, Reste von npm 0.x zu entfernen, was aber bei einer neuen Installation erstens überflüssig ist und was der Installer zweitens immer versucht, in /usr/local/lib/node zu tun, was mangels Rechten sowieso nicht funktioniert. Außerdem liegen dort ohnehin keine Node-Module.

node.js >= 0.6.5

Du brauchst nichts weiter zu tun; npm ist hier bereits vorinstalliert.

Das war's schon! Ab sofort kannst du jederzeit eigene Module mit npm installieren. Aber …

Probleme mit tar

Die Installation einiger beliebter Module wie zum Beispiel socket.io oder express.js schlägt mit Fehlern fehl, die darauf zurückzuführen sind, dass die von uns zentral bereitgestellte Version von tar nicht aktuell genug ist - wobei wir jene aber aufgrund des von unserer Linux-Distribution umgesetzten Backporting-Prinzips auch nicht einfach global aktualisieren können, ohne dass es dabei möglicherweise an anderer, unerwarteter Stelle zu Problemen kommen könnte. Du kannst dir aber einfach selbst ein frischeres tar in deinem Uberspace installieren - das braucht nur einen Befehl und eine Minute Zeit:

[mareike@neon ~]$ toast arm tar

Anschließend ist auch die zuvor fehlgeschlagene Installation der npm-Pakete problemlos möglich. In unserem Artikel zu toast findest du detailliertere Dokumentation für dieses Anwendungsbeispiel von toast.

lokal vs. global

Standardmäßig installiert npm Module immer im Unterverzeichnis node_modules im Startverzeichnis deiner Applikation (oder im aktuellen Verzeichnis, wenn es nicht herausfinden kann, was das Startverzeichnis deiner Applikation ist), und ggf. zugehörige Binaries in node_modules/.bin, wo sie außerhalb der Umgebungsvariable $PATH liegen. Das ist das, was mit „lokaler“ Installation gemeint ist: Nicht „lokal auf deinem Uberspace“, sondern „lokal im Applikationsverzeichnis“. Der Begriff „global“ meint demgegenüber hier nicht „systemweit“, sondern eher soviel wie „global für alle Applikationen, die du auf deinem Uberspace hast“.

Applikationen suchen, wenn du ein Modul mittels require('…') lädst, im applikationsspezifischen node_modules-Verzeichnis (das ist ein Feature von Node selbst, nicht von npm).

Benötigst du Module in mehreren Node-Applikationen, so gibt es zwei Möglichkeiten: Zunächst solltest du npm help link aufrufen und dich mit dem Symlink-Mechanismus vertraut machen, den Node für diese Fälle vorsieht. Trifft das nicht deinen Geschmack, so hast du die Möglichkeit, Module global auf deinem Uberspace zu installieren - mach dich hierzu bitte mit der FAQ vertraut, insbesondere mit den Abschnitten „How do I install something everywhere?“ und „No, I really want 0.x style 'everything's global' style.“ - auch wenn das ausdrücklich nicht empfohlen wird.

Detailliertere Informationen zu diesem Thema findest du in den Blogposts npm 1.0: Global vs Local installation und npm 1.0: link des npm-Autors.

Beispiel

Installieren wir doch mal exemplarisch den äußerst empfehlenswerten node-supervisor, und da dieser ein auszuführendes Script mitliefert, ist es eine äußerst gute Idee, ihn mittels -g global zu installieren:

[mareike@neon ~]$ npm install supervisor -g
/home/mareike/bin/node-supervisor -> /home/mareike/lib/node_modules/supervisor/lib/cli-wrapper.js
/home/mareike/bin/supervisor -> /home/mareike/lib/node_modules/supervisor/lib/cli-wrapper.js
supervisor@0.1.2 /home/mareike/lib/node_modules/supervisor

Nutzung mit den daemontools

Möchtest du einen Service anlegen, der zusätzlich den node-supervisor benutzt und somit deinen Code automatisch neu startet, wenn er sich ändert? Nichts leichter als das:

[mareike@neon ~] uberspace-setup-service exampleservice node-supervisor -w ~/example.js ~/example.js

Mehr Informationen

Felix Geisendörfer hat einen hilfreichen Node.js Guide verfasst, der dir hilft, schnell in die Details von Node.js vorzudringen (inklusive "Convincing the Boss"-Guide!).

development/nodejs.txt · Zuletzt geändert: 2012/05/05 11:30 von uber
Recent changes RSS feed Driven by DokuWiki Valid XHTML 1.0 Valid CSS