Die JavaScript-Community und damit auch die Node.js-Community entwickeln sich kontinuierlich weiter. Mittlerweile gibt es eine wahre Fülle von Bibliotheken und Packages, die einem als JavaScript- / Node.js-Entwickler zur Verfügung stehen. Seien es solche, die nur im Frontend Verwendung finden, solche, die auf Seiten des Backends angesiedelt sind oder sogar solche, die auf beiden Seiten eine gute Figur machen (Stichwort: Isomorphes JavaScript).
Die große Auswahl an Bibliotheken und Packages ist einerseits zwar Segen, kann andererseits aber auch ein Fluch sein: Monat für Monat, manchmal sogar Woche für Woche kommen neue Bibliotheken hinzu, und es fällt schwer, dabei immer die Übersicht zu behalten. Warum sollte man jetzt nochmal genau auf die neue Bibliothek umsteigen? Was macht diese besser als die 10 anderen, die doch das gleiche machen? Und für Neueinsteiger ist das Ganze auch nicht einfacher: bereits 2019 wurde in der offiziellen npm-Registry die Grenze von 1.000.000 Packages geknackt.
Ein guter Rat über diesen zugegebenermaßen teilweisen Irrsinn neuer Bibliotheken ist daher, nicht auf jeden Zug aufzuspringen, sondern sich stattdessen stetig seine Sammlung an Bibliotheken (seinen “Werkzeugkoffer”) sinnvoll und bedacht zu erweitern.
Im Folgenden möchte ich daher einige interessante Bibliotheken bzw. Node.js-Packages vorstellen, die meiner Meinung nach in keinem Werkzeugkasten eines Node.js-Entwicklers fehlen sollten. Die einzelnen Packages sind dabei in verschiedene Kategorien eingeteilt:
- Packages für die Arbeit mit Datums- und Zeitangaben
- Packages für das Verarbeiten von Webseiten
- Packages für die ID-Generierung
- Packages für das Ausführen von HTTP-Anfragen
- Packages für die Implementierung von Webservern
- Packages für sonstige Anwendungsfälle
Packages für die Arbeit mit Datums- und Zeitangaben
Einen Klassiker, den ich immer wieder nenne, wenn es um die Arbeit mit Datums- und Zeitangaben geht, ist Moment.js. Dieses Package vereinfacht die Arbeit mit Datums- und Zeitangaben erheblich. Wer schon einmal das “Vergnügen” hatte, sich mit der nativen Date API von JavaScript auseinanderzusetzen, weiß die Vorzüge von Moment.js schnell zu schätzen. Sei es das Parsen von Datums-Strings, das Formatieren der Ausgabe oder “Berechnungen” wie etwa das Ermitteln der Anzahl an Tagen zwischen zwei Zeitpunkten: kaum ein Anwendungsfall, für den Moment.js nicht vorgesorgt hat. Alternativ zu Moment.js lohnt sich ein Blick auf das Package date-fns, welches im Unterschied zu Moment.js keinen objektorientierten Ansatz, sondern einen funktionalen Ansatz verfolgt. Hier sollte man sich die beiden APIs einfach etwas genauer anschauen und das Package auswählen, welches dem persönlichen Programmierstil am ehesten zusagt.
Listing 1: Formatierung von Datums- und Zeitangaben mit Moment.js und date-fns
Ebenfalls erwähnenswert: mittlerweile gibt es mit der sogenannten Temporal API einen Vorschlag in der Arbeitsgruppe TC39 (also der Arbeitsgruppe, die hinter dem ECMAScript-Standard steht), welcher die Arbeit mit Datums- und Zeitangaben erheblich vereinfachen soll. Das Proposal befindet sich derzeit in Stage 2 des insgesamt fünfstufigen Prozesses, den neue Vorschläge durchlaufen müssen, um in den Standard mit aufgenommen zu werden. Es gibt zwar ein Polyfill-Package, welches die Temporal API schon heute implementiert, allerdings ist dieses Polyfill explizit nicht für den Produktiveinsatz geeignet. Bis zu dem Zeitpunkt, an dem die Temporal API in den Standard übernommen wird, bleiben also die zwei oben genannten Packages in jedem Fall relevant.
Packages für das Verarbeiten von Webseiten
Eine weitere Art von Tool, die in keinem Werkzeugkasten eines Node.js-Entwicklers fehlen darf, sind solche, mit denen sich Webseiten automatisch verarbeiten lassen, beispielsweise um Abläufe zu automatisieren oder Inhalte von Webseiten verarbeiten zu können. In den letzten Jahren haben sich diesbezüglich verschiedene Tools die Klinke in die Hand gegeben, sodass es lohnt, sich einen kurzen Überblick zu verschaffen.
Eines der ersten für Node.js relevanten Tools war vor einigen Jahren PhantomJS, ein sogenannter Headless Browser, mit Hilfe dessen sich Webseiten ohne „echten“ Browser – genauer: ohne visuelle Benutzeroberfläche – rendern und verarbeiten lassen. Dadurch eröffnet sich eine ganze Reihe von Anwendungsfällen, beispielsweise das Testen des Frontends einer Webanwendung auch auf CI-Servern, die selber keine grafische Oberfläche starten können.
PhantomJS war sicherlich wegweisend, wird inzwischen allerdings nicht mehr weiterentwickelt. Glücklicherweise stehen bereits verschiedene Alternativen zur Verfügung, die sich mindestens genauso komfortabel verwenden lassen. Hier sind insbesondere folgende Tools bzw. Packages nennenswert: Puppeteer, welches eine Headless API für den Chrome Browser zur Verfügung stellt, Playwright, welches eine API zur Verfügung stellt, über die es sogar möglich ist, neben Chrome auch Firefox und WebKit zu steuern sowie Selenium Webdriver, das insbesondere auf das automatisierte Testen von Nutzerinteraktionen innerhalb einer Webseite spezialisiert ist.
Alle drei APIs machen Gebrauch von Promises, sodass sich in Kombination mit den Schlüsselwörtern async und await jeweils sehr lesbarer Code ergibt. Folgendes Beispiel zeigt exemplarisch, wie einfach sich mit Playwright eine Webseite aufrufen und als Screenshots lokal speichern lässt:
Listing 2: Erstellen eines Screenshots mit Playwright
Packages für die ID-Generierung
Kaum ein größeres Web-Projekt, bei dem man nicht irgendeine Art von IDs benötigt. Sei es für das Speichern von Datensätzen in einer Datenbank oder das Design einer REST-API, um Ressourcen eindeutig zu identifizieren. Glücklicherweise muss man sich um die Generierung von IDs nicht selber kümmern, sondern kann auf praktische Node.js-Packages zurückgreifen.
Das Package uuid etwa hilft bei der Erstellung sogenannter UUIDs (“Universally Unique Identifier”). Dabei handelt es sich um 128-Bit große Zahlen, wobei man grundsätzlich zwischen verschiedenen UUID-Versionen unterscheidet, die letztendlich festlegen, auf welche Art und Weise die Generierung der UUID geschieht und welche Faktoren dabei berücksichtigt werden sollen.
Wem UUIDs zu kryptisch und zu lang sind, der hat lange auf das Package shortid zurückgegriffen. Allerdings sollte dieses Package laut eigenen Angaben aus Sicherheitsgründen nicht mehr verwendet werden. Eine Alternative findet sich in dem Package Nano ID, welches standardmäßig IDs der Länge 21 generiert. Wie in folgendem Listing zu sehen, lässt sich die Länge aber auch mit einem Parameter beeinflussen:
Listing 3: Generierung von UUIDs und Short-IDs
Packages für das Ausführen von HTTP-Anfragen
HTTP-Anfragen muss man recht häufig stellen. Sogar die Node.js Standard-API stellt mit dem „http“-Modul bereits Funktionalität für das Absenden von HTTP-Anfragen zur Verfügung. Doch es geht auch komfortabler. Sehr beliebt ist aktuell das Package axios: über entsprechende Methoden wie get() oder post() gehen HTTP-Anfragen deutlich einfacher von der Hand als unter Verwendung der Standard-API. Und auch das Verarbeiten der HTTP-Antworten ist um einiges einfacher:
Listing 4: Ausführen einer HTTP-Anfrage mit axios
Einziger Kritikpunkt von axios: es verwendet unter der Haube genau das besagte Modul aus der Node.js Standard-API, welches wiederum nicht auf Performance optimiert ist. Eine Alternative, die in dieser Hinsicht einen Blick Wert ist, ist das Package undici von Matteo Collina. Nicht zu empfehlen ist dagegen das einst (zurecht) beliebte Package request. Dieses wurde bereits 2018 als veraltet markiert und wird nicht mehr aktiv weiterentwickelt.
Packages für die Implementierung von Webservern
Wie schon für HTTP-Clients stellt Node.js über die Standard-API bereits ein Modul zur Verfügung, mit Hilfe dessen sich Webserver implementieren lassen. Allerdings gibt es eine ganze Reihe nützlicher Packages, die das Ganze noch weiter vereinfachen. Der Platzhirsch Express ist zwar immer noch sehr verbreitet und beliebt, hat in den letzten Jahren aber einiges an Konkurrenz bekommen. Das Package Koa gilt als inoffizieller Nachfolger von Express, wurde es doch vom gleichen Entwicklerteam ins Leben gerufen. Das Package restify konzentriert sich auf die Implementierung semantisch korrekter REST-APIs und ist insbesondere dann einen Blick Wert, wenn man lediglich eine REST-API implementieren möchte und das ganze „Drumherum“ von Express und Koa nicht benötigt. Das Package Fastify dagegen gilt im Vergleich zu den anderen genannten Packages als besonders performant, was durch verschiedene Benchmarks belegt wurde.
Listing 5: restify erleichtert die Implementierung von REST-APIs
Packages für das Verarbeiten verschiedener Formate
Auch wenn es um die Verarbeitung bzw. das Parsen verschiedener Datenformate geht, wird man unter Node.js fündig. HTML beispielsweise lässt sich über das Package Cheerio parsen. Praktischerweise stellt Cheerio die gleiche API zur Verfügung wie jQuery, sodass man sich als Frontend-Entwickler nicht umgewöhnen muss, um das HTML serverseitig verarbeiten zu können. Folgendes Listing zeigt, wie sich HTML mit Cheerio erst parsen und anschließend über aus jQuery bekannte Methoden verarbeiten lässt:
Listing 6: Cheerio kann HTML und XML verarbeiten
Doch Cheerio funktioniert nicht nur mit HTML, sondern auch mit XML. Es arbeitet dabei als sogenannter DOM-Parser, das heißt, das gesamte XML (bzw. HTML) wird in eine baumartige Struktur, das „Document Object Model“ geparst. Da dieses Objektmodell im Speicher vorgehalten wird, eignet sich diese Art des Parsens allerdings nur für kleine bis mittelgroße XML-Dokumente. Sehr, sehr große XML-Dokumente dagegen sollten stattdessen über einen sogenannten SAX-Parser wie beispielsweise sax-js geparst werden.
Wer CSS-Dateien automatisiert verarbeiten möchte, kommt um das Package PostCSS nicht herum. Insbesondere im Bereich der Frontend-Entwicklung ist dieses Package weit verbreitet, beispielsweise wenn es darum geht, im Rahmen des Build-Prozesses CSS zu optimieren, zu minifizieren oder in irgendeiner anderen Art und Weise zu verarbeiten oder zu transformieren. Über verschiedene Plugins lässt sich PostCSS modular erweitern und nach Belieben um eigene Transformationen anpassen. PostCSS parst CSS-Dateien in einen abstrakten Syntaxbaum (kurz „AST“ für „Abstract Syntax Tree“), welcher dann durch die konfigurierten Plugins verarbeitet und schlussendlich von PostCSS wieder als CSS ausgegeben wird.
Selbst für das Verarbeiten von JavaScript-Code selbst hat die Node.js-Community vorgesorgt: Esprima kann sowohl für die lexikalische Analyse (die sogenannte Tokenization) als auch für die syntaktische Analyse (das Parsen) verwendet werden. Wie PostCSS erhält man auch bei Esprima einen abstrakten Syntaxbaum, den man nach Belieben verändern kann – die Verwendung korrekter JavaScript-Syntax vorausgesetzt. Möchte man diesen abstrakten Syntaxbaum wieder in JavaScript-Code umwandeln, kann einem das Package Escodegen helfen. Mit der Kombination aus diesen beiden Packages lassen sich interessante Anwendungsfälle implementieren, vom simplen Ersetzen von Variablennamen bis zur Optimierung von JavaScript-Code im Rahmen des Build-Prozesses.
Listing 7: Mit Hilfe von Esprima lässt sich JavaScript-Code parsen
Packages für sonstige Anwendungsfälle
Neben den in den obigen Kategorien vorgestellten Packages gibt es eine ganze Reihe weiterer, die einen Blick Wert sind. Über dotenv beispielsweise lassen sich Umgebungsvariablen bequem über .env-Dateien konfigurieren und unter Node.js einlesen. Das Package semver dagegen hilft beim Parsen von semantischen Versionsnummern und das Package ShellJS stellt verschiedene unter Unix bekannte Kommandozeilentools in Node.js zur Verfügung. Wer dagegen selber Kommandozeilenanwendungen implementieren möchte, sollte einen Blick auf folgende Packages werfen: yargs und Commander.js nehmen einem einiges an Arbeit ab, wenn es beispielsweise um das Parsen von Parametern oder die Definition der Schnittstelle geht und mit Hilfe von Chalk wiederum lassen sich die Ausgaben auf der Kommandozeile nach Belieben einfärben.
25 Packages für Node.js-Entwickler – Fazit
Bereits dieser kurze Artikel hat gezeigt, welche Vielfalt an Packages für Node.js zur Verfügung stehen. Ob Verarbeitung von Datums- und Zeitangaben, das Erstellen von HTTP-Anfragen, die Implementierung eines Webservers oder das Parsen von Datenformaten. Kaum ein Anwendungsfall, für den man in der npm-Registry kein passendes Package findet. Dennoch sollte man bei der Auswahl eines Packages nicht auf jeden Zug aufspringen. Ein erster Indikator für die Qualität eines Packages können die Stargazer bei GitHub oder die „Weekly Downloads“ bei npm sein. Doch wichtiger als diese Kennzahlen sind die Antworten auf folgende Fragen: wer sind die Entwickler hinter dem Package? Wieviele Entwickler stehen hinter dem Projekt? Wie viele offene Issues gibt es für das Package? Werden Issues zeitnah beantwortet? Wann wurde das Package zuletzt aktualisiert? Wie oft wird das Package verwendet?
Darüber hinaus sollte geprüft werden, ob es bekannte Sicherheitslücken für das jeweilige Package gibt. Hierbei können Tools wie das seit Version 6 in der Installation von npm enthaltene npm audit helfen. Alternativen hierzu sind Snyk und Retire.js, die beide in der Lage sind, Node.js-Packages auf Schwachstellen hin zu überprüfen.
- 10 Web APIs, die Entwickler 2022 kennen müssen - 22. März 2022
- Eine Einführung in das IoT-Protokoll MQTT - 3. August 2021
- 25 Packages, die man als Node.js-Entwickler 2021 kennen muss - 4. Mai 2021