Unser NodeJS Starterkit
Maurice Renck
Bei der technischen Umsetzung von Diensten arbeiten wir gerne mit Microservices auf Basis von NodeJs. Microservices sind kleine Einheiten, die eine spezifische Aufgabe erfüllen und miteinander sprechen können.
Bei größeren Projekten kann es sein, dass wir viele solcher Microservices erstellen müssen. Natürlich wollen wir nicht jedes Mal von vorn beginnen, sondern unsere vergangenen Learnings direkt parat haben und vor allem: Zeit sparen.
Wir haben uns deshalb ein NodeJs-Microservice-Template erstellt, auf das wir für jeden neuen Service zurückgreifen.
Mit diesem Template haben wir einen Microservice in wenigen Minuten vorbereitet. Es beinhaltet alle Anbindungen, die potenziell wichtig sein könnten. Das sind beispielsweise Redis, MongoDB oder MariaDB.
Unser Setup beinhaltet entsprechend alle relevanten Pakete und Konfigurationen, wir könnten also sofort mit der Implementierung von Funktionen beginnen und dabei auf oben genannte Komponenten zugreifen.
Beim Entwickeln schauen uns diverse Skripte auf die Finger. Dank TypeScript sind wir generell typsicher unterwegs, Prettier, Linter und Unit-Tests mit Jest minimieren zudem das Risiko Fehler zu machen enorm.
Sogar unsere Commit-Nachrichten werden vor dem Senden geprüft! Wo wir können, nutzen wir Automatisierungen. Checken wir eine neue Funktion oder Fehlerkorrektur in unser Versionssystem (Git) ein, laufen einige Prozesse los.
Zunächst wird unser Code noch einmal geprüft, kompiliert und schließlich als Docker-Image bereitgestellt. Dieses Image kann dann auf den gängigen Plattformen installiert werden. Durch unsere readiness- und liveness-Proben sind unsere Images auch bereit für Kubernetes.
Damit nicht irgendetwas installiert wird, ermittelt einer unserer Prozesse eine neue, sinnvolle Versionsnummer. Diese ergibt sich aus dem Commit-Nachrichten.
Apropos Automatisierungen: Unser Setup informiert automatisch über Updates. Kleinere Fixes können bei Bedarf automatisch installiert werden, vor größeren Eingriffen stoppt das System und erstellt zunächst einen Pull-Request, den wir dann überprüfen können. Hierzu benutzen wir Renovate.
Durch ausgiebiges Logging haben wir immer Blick, was vor sich geht. Wie viel unsere Services uns erzählen sollen, lässt sich mit wenigen Handgriffen steuern. Damit wir auch service-übergreifend nachvollziehen können, was passiert, beinhaltet unser Logging die s.g. CorrelationId, die sich durch alle Systeme bewegt und mittels der wir den Weg einzelner Prozesse nachvollziehen können.
Für noch mehr Nachvollziehbarkeit erzeugen wir zudem automatisch API-Dokumentationen. So können alle Entwickler schnell mit der API arbeiten.
Auch wenn unser Starterkit schon ziemlich ausgereift ist, haben wir noch ein paar Tasks auf unserer Todo-Liste. Helm Charts beispielsweise, oder eine Open Telemetry Einbindung.
Generell entwickelt sich das Starterkit natürlich laufend weiter. Wenn wir an Microservices arbeiten, kommen wir immer wieder an Punkte, an denen es sinnvoll ist, neue Erkenntnisse zurück ins Starterkit zu spielen. Das ist nicht immer ganz einfach und eine der größeren Herausforderungen bei der Instandhaltung. Wichtig ist, so ein Starterkit nicht aus den Augen zu lassen, regelmäßige Dependency-Updates durchzuführen. Auch solche, die Renovate nicht automatisch vornehmen kann oder soll.
Für uns ist das Starterkit beides: Segen wie Herausforderung. Die Zeit, die wir letztlich bei jedem Microservice damit sparen, rechtfertigt aber die Pflege des Starterkits ohne Frage.
Wir würden allen Entwickler-Teams empfehlen, sich so ein Starterkit zu erstellen. Und wer das nicht kann oder gar kein Entwickler-Team hat, darf sich gerne bei uns melden und wir bauen dann in Windeseile die gewünschten Services 😉
Links
Wer doch lieber alles selber machen möchte, kann sich in folgenden Links weiter darüber informieren, welche Pakete und Dienste wir nutzen:
- Automatisch generierte API Dokumentation (Swagger) https://www.npmjs.com/package/tsoa
- Die optimierte CD/CI-Pipeline
- Commit Nachricht prüfen https://commitlint.js.org/#/
- Formatieren geänderter Dateien https://github.com/okonet/lint-staged
- Automatische Semantic Release Versionierung https://github.com/semantic-release/semantic-release
- Logging
- Frei konfigurierbares Logging https://github.com/winstonjs/winston
- Correlation ID https://github.com/puzpuzpuz/cls-rtracer
- Request Performance Logging https://github.com/expressjs/morgan
- Zentrale Fehler Aggregation https://github.com/getsentry/sentry-javascript
- Validierung von z.B. für Umgebungsvariablen https://github.com/colinhacks/zod
- Kubernetes-ready Applikationsstart https://github.com/godaddy/terminus