Teaser - Ausflug in die Welt der JavaScript Knoten

Ausflug in die Welt der JavaScript Knoten

Willkommen zurück! Heute geht es mal wieder etwas technischer zu. Über die Lernplattform Udemy, die ich in meinem Beitrag zur Fortbildung etwas näher beschreibe, bin ich zur Entwicklung mit Node.js gekommen. Was sich dabei zu Beginn als Segen herausstellte, wurde mit größer werdenden Projekten immer mehr zum Fluch. Es gibt viele Pakete auf denen man seinen eigenen Code aufbauen kann. Je mehr man davon verwendet, desto komplexer wird das Konstrukt und desto schwieriger wird es, diese Pakete immer auf dem Laufenden zu halten. Aber fangen wir vorne an.

Was ist Node.js

Node.js ermöglicht es mittels JavaScript, serverseitige Anwendungen zu entwickeln. Dazu wird die V8 Browserengine verwendet, die von Google ursprünglich für Chrome entwickelt wurde. Das besondere an Node.js ist zudem, dass alle blockierenden Aktionen, wie das Lesen und Schreiben von Festplatten oder auch Netzwerkzugriffe, in eigene Threads ausgelagert werden und somit zu nicht-blockierenden Aktionen werden. Das erlaubt trotz des Einzelprozesses in dem Node.js läuft, die Abarbeitung einiger tausend Abfragen in der Sekunde.

Node.js wurde 2009 in der ersten Version veröffentlicht und erfreut sich seitdem wachsender Beliebtheit. Während ich diesen Artikel schreibe (Anfang 2019) liegt die Version 11 vor und nicht immer war die Entwicklung von Harmonie geprägt. So wurde 2015 ein Fork namens io.js gegründet, da nicht alle Hauptentwickler mit der Richtung und der Geschwindigkeit des Projekts einverstanden waren. Diese Abspaltung war aber nur von kurzer Dauer und noch im selben Jahr wurde eine Stiftung gegründet unter deren Dach seitdem die Entwicklung abläuft.

NPM - Das Herzstück

Ich glaube die Plattform alleine wäre nicht da wo sie heute ist, wenn es nicht NPM geben würde. Damit kann jeder Entwickler seine Pakete veröffentlichen und es anderen somit erlauben, diese in eigenen Angwendungen zu verwenden. Wer erfindet schon gerne das Rad jedes Mal neu?

Unter npmjs.com kann man die Pakete durchsuchen, sich Statistiken zur Verwendung und der Pflege sowie die Versionen eines Pakets anschauen. In den Anfängen musste man sowohl Node.js als auch NPM separat installieren. Seit einigen Versionen ist aber NPM automatisch auf dem System installiert, sobald man Node.js eingerichtet hat.

Grundlagen

Schauen wir uns nun also an, wie das Ganze funktioniert. Dazu müsst ihr zuerst Node.js installieren. Über den Link gelangt ihr zur Startseite des Projekts, wo es immer zwei Versionen zur Auswahl gibt. Auf der linken Seite findet ihr die Version, die längeren Support bietet, während auf der rechten Seite die Version zu finden ist, die die neuesten Funktionen beinhaltet. Für die folgenden Ausführungen ist es egal, welche Version ihr installiert. Sobald ihr die Installation abgeschlossen habt, öffnet ihr am besten die Konsole eures Betriebssystems und führt diese Anweisungen aus:

node -v # v11.3.0
npm -v  # 6.4.1

Als Kommentar hab ich meine aktuellen Versionen angegeben, damit ihr seht, wie die Ausgabe aussehen sollte. Wenn ihr eine Fehlermeldung bekommt, dass eines der Kommandos nicht verfügbar ist, müsst ihr nochmals eure Installation prüfen. Gegebenenfalls findet ihr auch Hilfe im Internet.

Als nächstes müsst ihr einen neuen Ordner anlegen, indem wir ein kleines Projekt mit dem Fastify Web-Framework erstellen werden. Fastify ist ein junges aufstrebendes Projekt, das gegenüber bekannteren Vertretern wie Express ein paar Vorteile bietet:

  • Hochperformant: Das Projekt wirbt abhängig von der eigenen Codekomplexität von bis zu 30.000 Anfragen in der Sekunde
  • Erweiterbar: Fastify bietet Hooks, Plugins und Decorator an, um den Funktionsumfang zu erweitern
  • Schema-basiert: Auch wenn es keine Pflicht ist, kann man den JSON-Schema Standard verwenden, um Routen zu validieren
  • Logging: Normalerweise eine zeitintensive Aufgabe, nicht so bei Fastify, dort kommt ein Paket zum Einsatz, das die benötigte Zeit extrem reduziert

Achtet bei der Erstellung des Ordners darauf, dass der Name sich nicht mit einem Paket überschneidet, welches ihr verwenden wollt z.B. fastify in unserem Fall. Nachdem ihr in der Konsole in diesen Ordner gewechselt habt, gebt ihr folgenden Befehl ein:

npm init

Es werden euch als nächstes einige Fragen zum Projekt gestellt, die ihr für dieses erste Beispiel mit den Standardwerten - welche in Klammern stehen - bestätigen könnt. Zum Abschluss wird euch dann der Code der package.json Datei angezeigt, die erstellt wird sobald ihr mit [Enter] bestätigt. Diese Datei ist der Hauptbestandteil jedes Node.js Projekts. Darin stehen nämlich nicht nur die Informationen zu eurem Projekt, sondern mit zunehmender Entwicklungsdauer auch alle Abhängigkeiten, die euer Projekt hat. Mit dieser Datei ist es jedem anderen Entwickler möglich, die nötigen Pakete zu installieren.

Pakete installieren

Die Basis ist also geschaffen, nun müssen wir natürlich noch Pakete installieren, denn sonst ist unser Projekt relativ sinnfrei. Es gibt zwei Möglichkeiten ein Paket zu installieren. Entweder als Produktivabhängigkeit

npm i -S fastify

oder als Entwicklungsabhängigkeit

npm i -D mocha

Für unser Projekt braucht ihr jetzt nur den ersten Befehl ausführen und damit fastify installieren. Ich habe zu Demozwecken beide Befehle bei mir ausgeführt, was zu folgenden Abschnitten in der package.json Datei führt:

"dependencies": {
  "fastify": "^1.13.3"
},
"devDependencies": {
  "mocha": "^5.2.0"
}

Unter dependencies befinden sich alle Pakete, die unser Projekt für den produktiven Einsatz benötigt, während unter devDependencies die Pakete für die Entwicklungsphase aufgeführt sind. Das angegebene mocha Paket ist übrigens für Tests zuständig.

Paketversionen

Es gibt ein paar Punkte, die man beachten sollte, wenn es um die Versionen von Paketen geht. Wenn ihr ein Paket ohne Angabe einer Version installiert, wird immer die aktuellste vom Entwickler als stabil gekennzeichnete Version installiert. Der Eintrag in die package.json Datei wird automatisch von NPM vorgenommen und es wird ein ^ vorangestellt. Hier der Befehl, um zum Beispiel immer die aktuellste Version von fastify Version 1 zu installieren:

npm i -S fastify@1

Der Eintrag in der package.json verändert sich in diesem Fall nicht. Ihr könntet auch direkt @1.13.3 angeben und es würde dann mit jedem Aufruf von npm install (was immer alle Abhängigkeiten installiert), die aktuellste fastify Version installiert. In der Regel ist das kein Problem, wenn sich der Entwickler eines Pakets an die Konventionen hält und nur mit Hauptversionen Änderungen vornimmt, die nicht abwärtskompatibel sind. Ihr könnt die Versionen aber auch genauer festlegen. Dazu gibt es folgende Möglichkeiten:

  • 1.13.3 - Angabe ohne Sonderzeichen: Es wird immer genau diese Version installiert
  • 1.13 oder 1.13.x oder ~1.13.3: Diese Angaben führen dazu, dass immer die aktuellste Patch Version installiert wird. Das ist der letzte Teil der Nummer und beinhaltet in der Regel wichtige Fehlerbehebungen, die ihr natürlich haben wollt
  • 1 oder 1.x oder ^1.0.4: Standardfall: Damit werden automatisch alle Funktionsreleases (über die mittlere Nummer abgebildet) installiert. Mit solchen Releases werden kleinere Funktionen hinzugefügt, bestehende aber nicht verändert.
  • * oder x: Neueste Versionen: Mit Vorsicht zu genießen, da ihr damit keinen Einfluss auf die Version habt und unter Umständen euer Projekt nicht mehr läuft, wenn ihr die Pakete aktualisiert.

Ihr müsst natürlich von Fall zu Fall entscheiden, welche Version eines Pakets sinnvoll ist. Am besten schaut ihr euch auch immer die Releasenotes des jeweiligen Pakets an, um besser beurteilen zu können, welches Schema für dieses Paket am besten geeignet ist.

Startpunkt

Für diese Einführung brauchen wir erstmal keine weiteren Pakete. Der nächste Schritt besteht darin, den Einstiegspunkt von Fastify zu definieren. Dazu legt ihr im Basisverzeichnis eures Projekts eine Datei an, die ihr frei benennen könnt. Ich orientiere mich hier an der Dokumentation von Fastify und nenne sie server.js. In diese Datei fügt ihr folgenden Inhalt ein:

// Import des benötigten Pakets
const fastify = require('fastify')()

// Definition der ersten Route
fastify.get('/', (request, reply) => {
  reply.send({ hello: 'world' })
})

// Starten des Servers
fastify.listen(3000, (err) => {
  if (err) {
    fastify.log.error(err)
    process.exit(1)
  }
  fastify.log.info(`server listening on ${fastify.server.address().port}`)
})

Ihr startet den Server mit folgendem Kommando in der Konsole:

node server

Und das war es auch schon. Ihr könnt im Browser eurer Wahl zur Adresse http://localhost:3000 navigieren und solltet die JSON-kodierte Version von Hallo Welt sehen.

Natürlich ist das nur ein sehr einfaches Beispiel, aber es zeigt, wie schnell man mit Node.js eigene Projekte beginnen kann. Dieses Beispiel kann man jetzt beliebig erweitern. Hier eine Liste möglicher Zusätze:

  • Neue Routen: Ihr könnt weitere GET-/POST-Routen hinzufügen und ausprobieren
  • Statische Dateien: Ressourcen wie Bilder, CSS-Dateien oder JavaScript-Dateien werden statisch ausgeliefert. Ihr könnt versuchen, diese Funktion über die Dokumentation von Fastify zu finden und umzusetzen
  • Verwenden von Plugins: Fastify bietet eine lange Liste an Plugins, um bestimmte Funktionen nachzurüsten. Seht euch die Liste über das Ökosystem von Fastify an und probiert für euch interessante Funktionen umzusetzen

Nächste Schritte

Ich wollte euch in diesem Beitrag lediglich einen kurzen Einstieg in die wunderbare Welt der JavaScript Knoten geben. Dieses Thema ist jedoch so umfassend, dass darüber ganze Bücher geschrieben werden können. Wenn ihr euch weiter mit dem Thema beschäftigen wollt, gibt es natürlich einige Möglichkeiten. Ihr könnt euch in die Dokumentationen von Node.js, NPM und auch Projekten wie Fastify stürzen. Oder ihr macht es wie ich und sucht euch Videokurse zu den Themen die euch interessieren. Wenn ihr interessiert seid, könnt ihr mich jederzeit über das Kontaktformular im Fußbereich kontaktieren und ich kann euch gute Kurse auf Udemy empfehlen.

Ich persönlich finde Node.js eine extrem spannende Geschichte. Leider musste ich aber auch schon einige Rückschläge einstecken, die meinen Enthusiasmus etwas gedämpft haben. Je tiefer man in die Materie einsteigt und je ausgiebiger man bestimmte Pakete in seinen eigenen Projekten verwendet, desto schneller stößt man an Grenzen. Ich habe deshalb schon einige Pakete über GitHub forken müssen, um Anpassungen vornehmen zu können, die ich zwingend gebraucht habe. Oft sind es Fehler in den entsprechenden Paketen gewesen, aber auch fehlende Funktionen habe ich bereits eigenhändig nachpflegen müssen.

Ich werde euch in einem der nächsten Beiträge eines dieser Projekte vorstellen. Dazwischen werde ich noch den ein oder anderen Beitrag als Vorbereitung einschieben. Bleibt also gespannt!

Nun will ich euch aber nicht mehr länger aufhalten. Ich hoffe, ich konnte euch ein wenig für Node.js begeistern. Letztendlich müsst ihr nun für euch entscheiden, ob ihr dem Ganzen eine Chance gebt.