© 4 PM production/Shutterstock.com
Aufbau und Anwendung von Node.js

Ein Blick unter die Haube


2009 war die Geburtsstunde von Node.js und seitdem hat sich viel getan. Die Geschichte der serverseitigen JavaScript-Plattform ist voller Licht und Schatten. Mittlerweile hat sich Node.js jedoch in der Webentwicklung etabliert und kommt als Standalone-Server, im Verbund mit anderen Technologien, als Basis für Desktopapplikationen oder zur Entwicklung von Kommandozeilenwerkzeugen zum Einsatz. Grund genug für uns, einen Blick unter die Haube der Plattform zu werfen und herauszufinden, wie Node.js aufgebaut ist und wie es sich verwenden lässt.

Node.js erhebt nicht den Anspruch, eine Komplettlösung zu sein. Es ist vielmehr ein Werkzeugkasten, mit dem Sie Ihre Applikation aufbauen können. Allerdings müssen Sie sich darauf gefasst machen, dass Sie entweder sehr viel selbst implementieren oder zahlreiche zusätzliche Pakete installieren müssen. Der Grund hierfür ist, dass der Fokus von Node.js auf Flexibilität, Performance, Stabilität und Benutzbarkeit liegt.

  • Flexibilität: Mit den Schnittstellen von Node.js lässt sich nahezu jedes Problem lösen. Sie können auf Schnittstellen zum Betriebssystem, zum Dateisystem oder zum Netzwerk zurückgreifen. Diese Schnittstellen arbeiten jedoch auf einer sehr niedrigen Ebene und weisen nur einen überschaubaren Grad an Abstraktion auf. Für Sie bedeutet das, dass Sie beispielsweise im Fall eines TCP Streams die einzelnen Pakete entgegennehmen und behandeln müssen. Auf dieser Basis lassen sich jedoch alle TCP-basierten Protokolle abbilden.

  • Performance: Der Kern von Node.js ist recht überschaubar, der grundsätzliche Memory Footprint also auch entsprechend klein. Das liegt vor allem daran, dass der Kern von Node.js mit seinen Modulen über die Jahre klein gehalten wurde. Die Philosophie der Entwickler ist es, dass nur grundlegende Technologien implementiert werden. Alle weiteren Anforderungen müssen in zusätzliche Pakete ausgelagert werden. Neben dem geringen Speicherverbrauch ist auch die Laufzeitperformance bemerkenswert. Die V8 Engine, das Herzstück von Node.js, weist zahlreiche Optimierungen auf, die die Ausführung einer Applikation erheblich beschleunigen. Dazu aber später noch mehr.

  • Stabilität: Nach einer initialen Sturm-und-Drang-Phase hat sich die Node.js-Community schnell dazu entschlossen, die äußeren Schnittstellen der Plattform stabil und verlässlich zu halten. Und deshalb werden die Änderungen an dieser Stelle auf ein Minimum reduziert. Das wird beispielsweise durch den Stabilitätsindex der einzelnen Module deutlich. Ist ein Modul als stable gekennzeichnet, sind nur geringfügige Änderungen in den Major Releases der Plattform zu erwarten. Bei einem als experimental gekennzeichneten Modul müssen Sie mit Änderungen rechnen.

  • Benutzbarkeit: Reporting ist ein großer Punkt auf der Agenda der Node.js-Entwickler. Hiermit sind Schnittstellen gemeint, über die Sie Informationen über das Laufzeitverhalten von Node.js und Ihrer Applikation beziehen können. Der Ausbau dieser Fähigkeiten führt zu verbesserten Analyse- und Debuggingwerkzeugen. In diesem Bereich wird aktuell am stärksten gearbeitet.

Die Entwicklung von Node.js wird stark von der Community getrieben, und so finden sich zahlreiche Feature-Requests, die alltägliche Probleme in der Entwicklung mit Node.js adressieren. So wurden beispielsweise die Stacktraces bei Fehlern in asynchronen Funktionen verbessert, sodass trotz der Asynchronität eine Zuordnung zur aufrufenden Stelle im Code möglich ist und die Analyse von Fehlern erheblich vereinfacht wird.

Node.js weist einen mehrschichtigen Aufbau auf (Abb. 1). Um einen Kern mit der JavaScript Engine sind die Module der Plattform sowie externe Module und natürlich der Quellcode Ihrer eigenen Applikation angeordnet.

springer_node_1.tif_fmt1.jpgAbb. 1: Die Architektur von Node.js

Der Kern der Plattform

Den Kern bildet die V8 Engine. Sie stammt aus dem Chrome-Browser und ist für die Interpretation von JavaScript verantwortlich. Im konkreten Fall von Node.js wird als Einstiegspunkt in die Applikation eine Datei eingelesen, die laut Konvention den Namen index.js oder app.js trägt. Über das Modulsystem werden zusätzliche Dateien geladen. Die Dateien, die in Klartext vorliegen, werden von der Engine in Bytecode umgewandelt. Dieser Schritt wird als Just-in-Time Compilation bezeichnet. Der Bytecode wird zur Laufzeit der Applikation kontinuierlich optimiert, um beispielsweise Speicherzugriffe zu beschleunigen. Diese Optimierung führt allerdings auch dazu, dass der Quellcode bei Änderungen erneut eingelesen werden muss. Neben der JavaScript Engine sind noch weitere Bibliotheken, die in C und C++ geschrieben sind, Bestandteil des Kerns der Plattform. So übernimmt die Bibliothek libuv die Steuerung der asynchronen I/O-Operationen.

Die Kernmodule

Dieser Kern der Plattform wird von einer weiteren Schicht, den Node.js Bindings, umfasst. Diese Schicht ist erforderlich, da der Kern in C/C++ implementiert ist – der übrige Teil von Node.js besteht jedoch aus JavaScript-Code. Damit die Elemente aus beiden Welten miteinander interagieren können, ist eine solche Bindings-Schicht erforderlich. Auf ihr setzen schließlich die Kernmodule von Node.js auf. Hierbei handelt es sich um eine übersichtliche Anzahl lose gekoppelter Module, die Ihnen die Basisfunktionalität der Plattform zur Verfügung stellen. Beispiele für die Kernmodule sind das fs-Modul, über das Sie Zugriff auf das Dateisystem des Systems erhalten, oder das events-Modul, das eine Implementierung eines Event-Systems bietet. Die Module bauen teilweise aufeinander auf,...

Neugierig geworden?

Angebote für Teams

Für Firmen haben wir individuelle Teamlizenzen. Wir erstellen Ihnen gerne ein passendes Angebot.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang