Seit Node.js im November 2009 zum ersten Mal der Öffentlichkeit präsentiert wurde, hat es sich zu einem der beliebtesten JavaScript-Frameworks entwickelt. Node wird von Millionen Entwicklern und zahlreichen namhaften Unternehmen eingesetzt, zum Beispiel Google, Amazon Web Services, Microsoft, IBM, SAP, Netflix, Mozilla, PayPal, Trello und auch der Host-Europe-Mutter GoDaddy. Die Gründe dafür verraten wir Ihnen in diesem Überblicksartikel.
Was ist Node.js?
Node.js ist im Kern eine plattformunabhängige Laufzeitumgebung für JavaScript (geschrieben in C und C++), mit der die beliebte Skriptsprache für Web-Frontends auch außerhalb von Webbrowsern ausgeführt werden kann. Node wurde insbesondere für den Servereinsatz entwickelt, läuft aber auch auf Clients. Für Netzwerkanwendungen bietet es Ihnen einige technische Vorteile gegenüber klassischen Webserver-Technologien wie PHP:
- Node bewältigt mühelos Tausende paralleler Verbindungen.
- Node besitzt eine ressourcensparende, modulare Architektur für hohe Performance und Skalierbarkeit und niedrige Latenz.
- Node erleichtert die schnelle bidirektionale Kommunikation zwischen Client und Server, beispielsweise für Echtzeit-Anwendungen oder Single Page Applications (SPAs).
- Weil Node.js-Anwendungen in JavaScript geschrieben werden, können Entwickler die gleiche Sprache für Frontend- und Backend-Entwicklung verwenden.
Hunderttausende Module machen Node.js darüber hinaus zu einer leistungsfähigen Backend-Entwicklungsplattform. Es wird als Open-Source-Software vertrieben (MIT-Lizenz) und ist auf vielen Plattformen einsetzbar, darunter Linux, Microsoft Windows, MacOS, BSD, IBM AIX, Solaris, SmartOS sowie Android und iOS. Die Weiterentwicklung wird von der OpenJS Foundation koordiniert; alle zwei Jahre erscheint auch eine LTS-Version (Long Term Support).
Technischer Hintergrund: asynchron und ereignisgesteuert
Erfinder von Node.js ist der norwegische Entwickler Ryan Dahl. Dieser war mit den beschränkten Fähigkeiten gängiger Webtechnologien beim Umgang mit parallelen Verbindungen unzufrieden. Wenn eine klassische Webanwendung Daten einlesen oder schreiben muss, etwa bei einer Datenbankabfrage, startet sie den I/O-Prozess (Input/Output) und blockiert dann bis zu dessen Abschluss die weitere Ausführung (Blocking I/O). Um in dieser Zeit andere Aufgaben zu erfüllen, muss ein neuer Thread geöffnet werden. Der damals populärste Webserver Apache öffnete für jede Verbindung einen neuen Thread, was den Hardware-Ressourcenverbrauch (Arbeitsspeicher, CPU) in die Höhe trieb – insbesondere bei Tausenden gleichzeitiger Anfragen an populäre Webanwendungen.
Dahls Lösung war ein ereignisgesteuerter Ansatz mit einer sogenannten Event-Loop („Ereignisschleife“), wie ihn JavaScript-Engines in Browsern bieten (die etwa auf Klick-Ereignisse reagieren). Damit können innerhalb eines einzigen Threads (in Child-Prozessen) unterschiedliche Aufgaben und insbesondere I/O-Operationen mittels sogenannter Callback-Funktionen „asynchron“ abgearbeitet werden, ohne zu blockieren (Non-blocking I/O). So enthielt bereits die erste Version von Node.js, die Dahl am 8. November 2009 auf der European JSConf präsentierte, Googles damals brandneue JavaScript-Engine V8 (für Googles Browser Chrome), eine Event-Loop-Bibliothek, eine Low-Level-I/O-API, die anstelle der eigentlichen Funktionen alle I/O-Prozesse asynchron managt und kontinuierliche Datenströme erlaubt, sowie weitere „Module“ zur Unterstützung wichtiger Netzwerkfunktionen und Protokolle wie HTTP, TCP und DNS.
Module und Pakete
Modularität (gemäß CommonJS-Standard) war von Anfang an ein wichtiges Designmerkmal von Node. Einige Kernfunktionen werden als einkompilierte Module mitgeliefert (etwa Funktionen für asynchronen Netzwerk- und Dateisystemzugriff, die Arbeit mit Ereignissen, Puffer, Datenströme oder Protokolle wie HTTP und natürlich die JavaScript-Engine V8). Viele andere Funktionen können Sie bei Bedarf über zusätzliche Module nachrüsten, die als einzelne Dateien (JavaScript oder vorkompiliert) oder auch umfangreiche Sammlungen von Dateien und Ordnern vorliegen können. Sie können dafür Ihre eigenen lokalen Module erstellen oder fertige Module anderer Entwickler nutzen.
Schon 2010 erschien der Paketmanager npm (ursprünglich „Node Package Manager“), der die Veröffentlichung, Einbindung und Verwaltung externer Node-Module und ihrer Abhängigkeiten erheblich vereinfachte. Heute hostet die npm Registry über eine Million JavaScript-Pakete (nicht nur für Node.js) und bezeichnet sich als größte Software-Registry der Welt.
So stehen die Chancen gut, dass Sie für jeden gewünschten Zweck auch ein passendes Node-Paket finden – wenn Sie es denn finden, denn die große Auswahl erschwert natürlich die Suche. Hier kommen Webframeworks wie Express, Hapi oder Koa ins Spiel, die eine Vorauswahl nützlicher Pakete bieten und die Entwicklung erheblich vereinfachen. Hilfreiche Pakete sind beispielsweise GraphQL für API-Datenabfragen, Cheerio (jQuery für Server), Passport für Authentifizierungsaufgaben, die Testumgebung Mocha oder Socket.IO für die bidirektionale Kommunikation mit dem Client (siehe unten).
Welche Anwendungen profitieren am meisten von Node.js?
Node.js läuft plattformunabhängig auf Servern und Clients und sogar auf Mikrocontrollern. Daher können Sie Node für die verschiedensten Zwecke einsetzen, nicht nur für Webserver und andere Backendanwendungen, sondern auch zum Beispiel für Client-Apps auf Desktop- oder Mobilgeräten, als Webserver für das Backend oder für IoT-Anwendungen. Besonders zu empfehlen ist Node für die folgenden Bereiche.
Klassische Webanwendungen mit hoher Performance
Node.js ist auf eine hohe Geschwindigkeit bei Netzwerkanwendungen mit zahlreichen parallelen Verbindungen und hohen Bandbreitenanforderungen optimiert. Die ereignisgesteuerte Architektur und das modulare Konzept sorgen für minimalen Overhead und niedrigen Speicherbedarf. Insbesondere bei einfachen Aufgaben bietet die Umgebung eine außergewöhnliche Performance und es eignet sich damit hervorragend auch für datenintensive Webanwendungen mit hohen Zugriffszahlen, bei denen es auf Leistung und Skalierbarkeit ankommt.
Dank Tausender npm-Pakete können Sie mit Node auch komplexere Anwendungen schnell erstellen. Ein weiterer wesentlicher Vorteil von Node besteht darin, dass Frontend- und Backendanwendungen mit der gleichen Programmiersprache und in der gleichen Umgebung entwickelt werden können. Wer sich gut mit JavaScript auskennt, muss sich nicht unbedingt in PHP oder eine andere Sprache einarbeiten. Zum Teil lassen sich auch Code-Teile auf Fontend- und Backendseite wiederverwenden.
Singe-Page-Apps
Single-Page-Anwendungen, kurz SPAs, präsentieren auch umfangreichen Web-Content auf einer einzelnen Seite. Einmal vom Server geladen, reagiert eine solche SPA schneller auf Benutzerinteraktionen und fühlt sich bei der Bedienung ähnlich an wie eine native Anwendung.
Natürlich muss auch der Webserver neben dem Ausliefern der SPA weiterhin andere Aufgaben übernehmen, etwa Authentifizierung und Autorisierung von Nutzern oder die Validierung, Speicherung und Synchronisierung von Daten. Außerdem kann bei umfangreichen SPAs durch serverseitiges Rendering (SSR) einiger Inhalte der Seitenaufbau beschleunigt werden. Auch wenn sich auf Serverseite etwas ändert, muss der Server aktiv werden, denn sonst bekommt die SPA das nicht ohne Weiteres mit.
In allen diesen Fällen kann Node Ihnen helfen. Es erlaubt auf einfache Weise SSR, eine effiziente bidirektionale Kommunikation zwischen Server und Client und das schnelle asynchrone (nicht-blockierende) Laden verschiedener Inhalte wie JavaScript-Code und anderer Ressourcen. Zudem arbeitet Node gut mit SPA-Frameworks wie Angular, React und Vue zusammen, für die es auch diverse npm-Pakete gibt.
Microservices
Die Module in Node.js kapseln ihre Funktionen und stellen sie über Programmierschnittstellen (Application Programming Interfaces, APIs) für Anwendungen bereit (ähnlich wie Browser-APIs für JavaScript-Frontends). Node.js eignet sich damit perfekt für die Umsetzung von Microservice-Architekturen.
Microservices sind ein architektonischer Ansatz, der darauf basiert, eine Anwendung als Sammlung kleinerer, voneinander unabhängiger Dienste aufzubauen. Das vermeidet diverse Probleme monolithischer Software, bei denen Code-Änderungen oder Fehler stets die ganze Anwendung betreffen und die wesentlich unflexibler entwickelt, gewartet und skaliert werden können. Mit Node können Sie mit wenig Aufwand Microservices und Container nutzen und flexible, skalierbare Anwendungen mit moderner Architektur erstellen.
Echtzeitanwendungen
Die bidirektionale Kommunikation mit Clients ist insbesondere für Echtzeitanwendungen notwendig. Wenn sich etwa auf Börsenseiten oder in Chat-Apps und Kollaborationstools Daten auf dem Server ändern, müssen sie möglichst sofort auch auf den jeweiligen Clients aktualisiert werden. Auch dafür ist Node.js prädestiniert – nicht nur durch seine APIs, die Daten in nahezu Echtzeit bereitstellen, sondern vor allem durch seine ereignisbasierte Architektur und die Unterstützung von WebSockets.
WebSocket ist ein Netzwerkprotokoll, das mit HTTP kompatibel ist und dessen Ports 443 und 80 nutzen kann. Aber anders als HTTP ermöglicht es bidirektionale Verbindungen zwischen Webanwendung und Server. Denn während bei HTTP der Server nur auf Anfragen des Clients antworten kann und danach die dafür aufgebaute TCP-Verbindung wieder beendet wird, bleibt bei WebSocket-Anfragen die Verbindung nach einer Anfrage offen. Dann kann auch der Server von sich aus ohne neue Anfrage Informationen an den Client senden.
Moderne HTML5-Anwendungen können WebSockets nutzen. Node.js unterstützt die Technologie mittels diverser Pakete, darunter auch das schon erwähnte Paket Socket.IO, welches zudem weitere Funktionen bietet, die über WebSocket hinausgehen, darunter Eventsteuerung, Broadcasting, die Speicherung clientspezifischer Daten und asynchrones I/O. So bauen Sie mit Node erfolgreich leistungsfähige Echtzeitanwendungen – Socket.IO kommt beispielsweise in Microsoft Office, Yammer oder Zendesk zum Einsatz.
Streaming
Mit seinem ausgelagerten, asynchronen (non-blocking) I/O kann Node besonders effizient mit Echtzeit-Datenströmen umgehen. Node kann beispielsweise umfangreiche Dateien bereits während des Hochladens ver- bzw. bearbeiten oder bei der Auslieferung in Echtzeit auf Client-Eingaben reagieren (etwa zum Steuern der Videowiedergabe). Für die Arbeit mit Streams bietet Node ein eigenes Modul (node:stream) an, das APIs für das Lesen und Beschreiben von Datenströmen bereitstellt. Dank seiner Leistungsfähigkeit ist Node eine gute Wahl für Streaming-Anwendungen etwa für Video- und Audiodateien, aber auch Online-Games oder die Verarbeitung von Sensordaten. Ein interessantes Beispiel ist Netflix, das seine NodeQuark-Infrastruktur für das Webstreaming an seine 100+ Millionen Nutzer, aber auch in der Content-Produktion verwendet.
Das richtige Hosting
Node.js gibt sich mit sehr bescheidenen Hardwareressourcen zufrieden und kann sogar auf einem alten Raspberry Pi installiert werden. Die tatsächlich benötigte Leistung hängt somit von der damit umgesetzten Anwendung und ihrer erwarteten Nutzung ab. Da Node.js vor allem für daten- und bandbreitenintensive Anwendungen mit vielen parallelen Zugriffen verwendet wird, sollten Sie nicht an Arbeitsspeicher und CPU-Kernen sparen.
Mit Shared-Hosting-Angeboten werden Sie beim Betrieb Ihrer Node-Anwendung wahrscheinlich nicht glücklich werden. Empfehlenswert ist ein Server mit Root-Zugriff, mindestens 2 GB RAM, 4 vCPU-Cores (oder Dual-Core-CPU bei dedizierten Servern), schnellem Massenspeicher und guter Netzwerkanbindung. Bei Host Europe finden Sie passende Virtual Server oder Dedicated Server mit flexibel wählbarer Ausstattung.
Neugierig geworden? Wenn Sie mehr über Node.js wissen möchten, werfen Sie doch einmal einen Blick auf diese Blogartikel:
- 20 Punkte, die Sie bei der Erstellung Ihrer ersten Node.js-Anwendung beachten sollten
- 7 native Neuerungen in Node.js, die Sie 2022 kennen sollten
- 25 Packages, die man als Node.js-Entwickler 2021 kennen muss
- js: Die performante Plattform für Webserver und mehr
- Von vorne bis hinten: Angular ♥ NestJS