Programmieren mit Node.js und Javascript

lightwise, 123RF

Turbulente Welt

Nie war die Entwicklung von Webanwendungen so komplex wie heute und nie gab es dafür so viele Bibliotheken und Frameworks. Das Javascript-basierte Node.js bildet einen ganz besonderen Mikrokosmos, in den dieser Artikel einführt.
Das Titelthema im ADMIN 04/14 "Vernetzt speichern" sind Netzwerkdateisysteme, etwa Samba 4, verteilter Storage mit Ceph & GlusterFS und der Unix-Klassiker ... (mehr)

In der Webentwicklung kommen und gehen die Trends schneller als die Sommer- und Wintermode. Eine Zeit lang war Ruby on Rails der letzte Schrei, jetzt ist es um das Framework etwas ruhiger geworden und die Aufmerksamkeit gilt Javascript, das als alleinige Programmiersprache auf Clients und auf dem Server laufen soll, wenn es nach dem Willen seiner Anhänger geht. Serverseitige Javascript-Frameworks gibt es schon eine Zeit lang, etwa Helma [1] , auf dem die Website des österreichischen Rundfunks ORF basierte. Helma wird langsam eingemottet, aber ein Nachfolger namens Ringo steht schon in den Startlöchern.

Projekte wie diese waren aber verglichen mit Rails und PHP-Frameworks immer nur Nischenprodukte.

Anders verhält es sich mit Node.js [2] (kurz Node), das seit einigen Jahren extrem populär ist und eine große Entwickler-Community um sich gesammelt hat. Entwickelt wurde es von Ryan Dahl, der den Google-Javascript-Compiler V8 mit einigen nichtblockierenden C-Bibliotheken koppelte, deren Funktionen in Javascript zur Verfügung stehen. Das ermöglicht die Event-basierte Verarbeitung von Netzwerkanfragen und somit mehr gleichzeitige Requests als etwa der Apache-Server beherrscht – der allerdings in neueren Versionen auch ein Event-basiertes Verarbeitungsmodul besitzt [3] .

Viel Auswahl

Eine der Stärken von Node.js und ein Resultat seiner großen Popularität ist die riesige Zahl an Modulen, die den Funktionsumfang erweitern. Dabei geht der Hype mittlerweile so weit, dass Node nicht mehr auf Webanwendungen beschränkt ist, sondern sogar für klassische Systemwerkzeuge verwendet wird. So basieren die Administrations-Tools in SmartOS [4] auf Node – was vielleicht weniger erstaunlich ist, wenn man weiß, dass Joyent, die Firma hinter SmartOS, die Projektleiter von Node beschäftigt und sich als "Steward" des Projekts versteht. Auch Microsoft stellt zur Verwaltung der Azure Cloud per Kommandzeile auf Linux und OS X ein Tool zur Verfügung, das auf Node basiert [5] .

Installieren lässt sich Node ziemlich einfach. Die meisten Linux-Distributionen führen es mittlerweile in ihren Repositories, aber das ist selten eine aktuelle Version. Besser ist es, den Quellcode herunterzuladen, zu entpacken und mit »make« und »make install« zu installieren. Dafür nötig sind diverse Entwicklungspakete, etwa die Libev. Für Ubuntu gibt es aktuelle Node-Versionen auch im Repository »ppa:chris-lea/node.js« .

Nach der Installation finden sich die beiden Kommandos »node« und »npm« auf der Festplatte, meistens im Verzeichnis »/usr/local/bin« . Die mitgelieferten Module sind per Default in »/usr/local/lib/node_modules/« gespeichert. Außer auf Linux läuft Node auch auf OS X, (Open) Solaris und Windows.

Wie angedeutet handelt es sich bei Node in erster Linie um einen Javascript-Compiler/Interpreter mit Zusatzbibliotheken. Wer »node« auf der Kommandozeile startet, landet auf einem Prompt, der Javascript-Befehle und -Funktionen akzeptiert:

> "admin".toUpperCase()
'ADMIN'

Typischerweise arbeitet man mit Node genauso wie mit anderen Skriptsprachen: Man schreibt seinen Code in eine Datei und führt sie mit »node« aus. Weil Node seine Fähigkeiten besonders als Webframework entfaltet, ist das klassische Hello-World-Beispiel ein kleiner Webserver, der in wenigen Zeilen programmiert ist. Das dafür nötige Modul »http« wird Javascript-typisch mit »require« geladen und an eine normale Variable gebunden:

var http = require('http');

Die Funktion »createServer« des HTTP-Moduls erwartet als Argument eine Funktion, die beim Auftreten eines Request-Events ausgeführt wird. In Listing  1 übernimmt das eine anonyme Funktion mit je einem Parameter für den Request und für die Antwort an den Client. Im Funktionsrumpf schreibt die Funktion »writeHead« erst den Header und erwartet dafür den Response-Code und einen optionalen Hash der Header. Die Funktion »end« gibt normalerweise das Ende von Header und Body an, das die Funktion »write« übermittelt. In diesem Fall erledigt »end« alles in einem Aufwasch, wenn man ihr die Nutzdaten übergibt. Steht der Code etwa in einer Datei namens »server.js« , startet ein Aufruf von »node server.js« den Server auf Port 3000. Auf dieser Basis könnte man anfangen, seinen eigenen Webserver aufzubauen, indem man in der Request-Methode Fallunterscheidungen einbaut, die je nach URL zu anderen Funktionen springen. Das ist allerdings recht mühsam, deshalb haben Node-Anwender diverse Module geschrieben, die das URL-Routing vereinfachen. Das populärste derartige Modul ist Express [6] , das in den meisten Webanwendungen zum Einsatz kommt, und das noch weitere praktische Funktionen bietet. Eine Alternative wäre etwa der Director aus dem Flatiron-Projekt.

Listing 1

Simpler Webserver

 

Node-Pakete

Installiert werden externe Module mit dem Paketmanager NPM, der in der Node-Distribution enthalten ist. Von Hand installiert man ein Paket mit einem Aufruf von »npm install Modul« . Die Module landen im Unterverzeichnis »node_modules« des aktuellen Verzeichnisses; systemweites Installieren von Node-Modulen mit dem Schalter »-g« ist normalerweise verpönt, außer es handelt sich um ein Modul, das ein aufrufbares Kommando enthält. Die Idee ist, dass so jede Node-Anwendung mit genau denjenigen Versionen von Modulen arbeiten kann, die es braucht und die nicht unbedingt mit denen einer anderen Node-Anwendung identisch sind. Wird ein Modul per »require« in eine Node-Anwendung eingebunden, sucht Node aber nicht nur im aktuellen Verzeichnis, sondern in allen höheren Ebenen, bis hin zum Root-Verzeichnis. So ließe sich also auch ein Repository von Node-Modulen pflegen, das mehreren Anwendungen zur Verfügung steht, wenn man dies wünscht.

Ist das Express-Modul mit »npm install express« installiert ( Abbildung 1 ), bindet man es wie gehabt mit »var express = require('express')« ein. Listing  2 zeigt, wie man die Webanwendung mit Express strukturiert. Eine Express-Anwendung wird durch einen Aufruf der Funktion »express()« erzeugt, die im Weiteren als Schaltpunkt dient. Das Routing findet in Zeile 11 statt. Dabei wird durch den Aufruf derjenigen Express-Methode, die so heißt wie die gefragte HTTP-Methode, eine Verknüpfung zwischen URL und aufzurufender Funktion hergestellt. Im Beispiel führt also der Aufruf von »app.get()« dazu, dass beim Aufruf der URL »/« per HTTP-GET die Funktion »root« abläuft. Um für dieselbe Adresse eine Aktion einem HTTP-POST-REQUEST zuzuweisen, würde man »app.post()« verwenden.

Listing 2

Express-Webserver

 

Abbildung 1: Die Installation des Express-Moduls zieht die Installation einer Vielzahl anderer Pakete nach sich.

Auch hier läuft der Server wieder auf Port 3000, wenn man das Programm zum Beispiel mit »node app.js« startet. Besucht man mit dem Webbrowser die Adresse »http://Servername:3000« , stößt man auf die Hello-Nachricht.

Ähnliche Artikel

comments powered by Disqus
Einmal pro Woche aktuelle News, kostenlose Artikel und nützliche ADMIN-Tipps.
Ich habe die Datenschutzerklärung gelesen und bin einverstanden.

Konfigurationsmanagement

Ich konfiguriere meine Server

  • von Hand
  • mit eigenen Skripts
  • mit Puppet
  • mit Ansible
  • mit Saltstack
  • mit Chef
  • mit CFengine
  • mit dem Nix-System
  • mit Containern
  • mit anderer Konfigurationsmanagement-Software

Ausgabe /2023