- Node.js entwickelt sich zuletzt schnell weiter, indem Funktionen, die bisher nur mit npm-Paketen möglich waren, direkt in die Runtime integriert werden
- Dadurch werden Supply-Chain-Sicherheitsrisiken reduziert, die Portabilität von Code verbessert, Abhängigkeiten verringert und die Wartung vereinfacht, was dazu beiträgt, Leistung und Stabilität in Produktionsumgebungen sicherzustellen
- Durch die Ergänzung globaler APIs wie
fetch(), WebSocket, node:test ist Entwicklung auch ohne bekannte Pakete wie node-fetch, ws oder mocha möglich
- Durch die Erweiterung der Dateisystemfunktionen stehen als Ersatz für
glob, rimraf, mkdirp nun Optionen wie fs.glob(), fs.rm(), fs.mkdir() zur Verfügung
- In den Utility- und Kryptografie-APIs sind
crypto.randomUUID(), util.styleText(), atob/btoa u. a. standardmäßig enthalten, sodass Pakete wie uuid oder chalk nicht mehr nötig sind
- Einige Funktionen (
node:sqlite, URLPattern, --env-file, TypeScript-Ausführung usw.) befinden sich noch in der experimentellen Phase
- Wichtig ist, dass durch die Weiterentwicklung von Node.js moderne Anwendungsentwicklung bereits mit der Standard-Runtime allein möglich wird
Wichtige npm-Pakete, die durch integrierte Node.js-Funktionen ersetzt wurden
- Node.js war lange auf verschiedene npm-Pakete angewiesen, etwa für HTTP-Utilities oder Dateisystem-Helfer
- In neueren Versionen (v18 bis v22) verstärkt sich jedoch der Trend, diese Funktionen direkt in die Runtime zu integrieren
- Dadurch sinken die Komplexität der Paketverwaltung und das Risiko von Sicherheitslücken
1. node-fetch → Globales fetch()
- Seit Node.js 18 wird dasselbe
fetch() wie im Browser als globale Funktion bereitgestellt
- HTTP-Anfragen lassen sich damit auch ohne
node-fetch verarbeiten
- In v17.5.0 experimentell eingeführt, in v18.0.0 stabilisiert
- Für Versionen vor 18 ist
node-fetch jedoch weiterhin erforderlich
2. ws → Globales WebSocket
- Seit Node.js 21 wird die clientseitige WebSocket-Verbindung über eine globale
WebSocket-Klasse unterstützt
- In v21.0.0 experimentell hinzugefügt, bis heute noch experimentell
- Für serverseitige WebSocket-Implementierungen werden weiterhin das Paket
ws oder ähnliche Bibliotheken benötigt
3. Test-Frameworks → node:test
- Seit Node.js 18 gibt es mit dem integrierten Test-Runner
node:test eine Alternative zu mocha, jest usw.
- In v18.0.0 experimentell eingeführt, in v20.0.0 stabilisiert
- Unterstützt das Schreiben und Ausführen grundlegender Unit-Tests
- Wenn Snapshots, Mocks oder umfangreiche Plugins benötigt werden, bleiben Third-Party-Frameworks weiterhin nützlich
- Für Tests auf Modulebene ausreichend, bei Full-Stack-Anwendungen haben bestehende Frameworks weiterhin Vorteile
4. sqlite3 / better-sqlite3 → node:sqlite
- In Node.js wird derzeit das experimentelle Modul
node:sqlite für den SQLite-Zugriff eingeführt
- Es behebt Kompilierungsprobleme und Upgrade-Fehler bestehender Pakete mit nativen Bindings
- Unterstützt grundlegende Aufgaben wie In-Memory-Datenbanken und das Erstellen von Tabellen
- Da es sich noch um eine experimentelle Funktion handelt, werden bei erweitertem Performance-Tuning oder zusätzlichen Features weiterhin Community-Pakete empfohlen
5. chalk / kleur → util.styleText()
- Seit Node.js 20.12.0 ist Konsolen-Textstyling mit
util.styleText() möglich
- In v22.17.0 stabilisiert
- Unterstützt grundlegende Textstile wie Farben, Fettdruck und Unterstreichung
- Wenn komplexe Themes, Chaining-Syntax oder Abwärtskompatibilität benötigt werden, kann
chalk weiterhin verwendet werden
6. strip-ansi → util.stripVTControlCharacters()
- Die Entfernung von ANSI-Escape-Codes wird als integrierte Node.js-Funktion bereitgestellt
- Steuerzeichen lassen sich damit sicher aus Logs entfernen
- Die meisten Anwendungsfälle werden nativ abgedeckt, sodass kein Third-Party-Paket nötig ist
7. glob → fs.glob()
- Seit Node.js 22 gibt es mit
fs.glob() eine integrierte Funktion für die Suche nach Dateimustern
- In v22.0.0 hinzugefügt, in v22.17.0 LTS stabilisiert
- Dateisuche mit Glob-Mustern wie
**/*.js
- Wenn Kompatibilität zu älteren Node.js-Versionen erforderlich ist, wird weiterhin das Paket
glob verwendet
8. rimraf → fs.rm({ recursive: true })
- Rekursives Löschen von Verzeichnissen wird durch die native Node.js-API unterstützt
- Über die Optionen
recursive und force von fs.rm() umgesetzt
- Seit etwa v12.10.0 verfügbar, inzwischen in allen LTS-Versionen stabilisiert
- Verzeichnisse lassen sich damit sicher auch ohne das Paket
rimraf löschen
9. mkdirp → fs.mkdir({ recursive: true })
- Rekursives Erstellen von Verzeichnissen wird über die Option
recursive von fs.mkdir() bereitgestellt
- Seit v10.12.0 verfügbar und seit Langem stabilisiert
- Verschachtelte Verzeichnisse lassen sich ohne separates Paket erstellen
10. uuid → crypto.randomUUID()
- Seit Node.js 14.17.0 gibt es mit
crypto.randomUUID() eine Funktion zur UUID-Erzeugung
- Als stabile Funktion im Kryptografie-Modul enthalten
- Sichere zufällige IDs lassen sich damit ohne das Paket
uuid erzeugen
11. base64-js / atob → atob, btoa
- Seit Node.js 20 stehen die globalen Funktionen
atob und btoa zur Verfügung
- Dieselbe Base64-API zum Kodieren/Dekodieren wie im Browser
- Zusätzliche Optionen neben dem bisherigen
Buffer
- Base64-Verarbeitung ist damit ohne Polyfill möglich
12. url-pattern → URLPattern
- Seit Node.js 20 wird die globale
URLPattern-API experimentell bereitgestellt
- Unterstützt Route-Matching, Extraktion von Pfadparametern usw.
- Noch experimentell und weiter stabilisierungsbedürftig
- URL-Muster lassen sich damit über eine standardisierte Web-API verarbeiten
13. dotenv → --env-file-Flag
- Seit Node.js 20.10.0 wird das Laden von Umgebungsvariablen über das
--env-file-Flag unterstützt
- Lädt beim Ausführen direkt eine
.env-Datei
- Noch experimentell
- Für Variablenerweiterung, mehrere env-Dateien und andere erweiterte Funktionen wird weiterhin das Paket
dotenv benötigt
14. event-target-shim → EventTarget
- Seit Node.js 15.0.0 wird das Web-Standard-Ereignissystem
EventTarget global bereitgestellt
- In v15.4.0 stabilisiert
- Unterstützt dasselbe Ereignismodell wie im Browser
- Kann als Alternative zu
EventEmitter verwendet werden
15. tsc → TypeScript-Ausführung in Node.js
- Seit Node.js 21 lassen sich mit dem Flag
--experimental-strip-types .ts-Dateien direkt ausführen
- Entfernt nur Typen, unterstützt jedoch kein vollständiges Type-Checking
- Noch experimentell
- Für Produktions-Builds, statische Typprüfung, das Erzeugen von Deklarationsdateien und vollständiges Type-Checking wird weiterhin
tsc benötigt
Fazit
- Die Entwicklungsrichtung von Node.js besteht darin, die Abhängigkeit von externen Paketen zu verringern und die Plattform selbst zu vervollständigen
- In der aktuellen LTS-Version (v22) sind bereits viele npm-Pakete überflüssig geworden,
was erhebliche Verbesserungen bei Sicherheit, Performance und Wartbarkeit bedeutet
- In Unternehmensumgebungen wird zur Echtzeitbeobachtung dieser Veränderungen N|Solid eingesetzt
- Analyse der tatsächlichen Workload-Performance integrierter Funktionen (
fetch, node:test, crypto.randomUUID() usw.)
- Der KI-Agent N|Sentinel überwacht die Nutzung und gibt Empfehlungen zur Optimierung auf Code-Ebene
6 Kommentare
Die von der Runtime bereitgestellten APIs werden immer zahlreicher..
Besonders bei Netzwerk-APIs, URL- und String-Verarbeitungs-APIs wie b64 usw...
Das ist ja komplett... PH..
Anscheinend ist UUID v7 noch etwas zu früh dran.
Ich finde, dass man DB-Treiber aus einer anderen Perspektive betrachten sollte als Funktionen, die in andere Standardbibliotheken gehören. Sowohl bei bun als auch sonst stellt sich die Frage: Warum will man einen SQLite-Treiber in die Runtime integrieren?
Liegt es daran, dass Python ihn eingebaut hat?
Ich denke, wichtiger als SQLite-Funktionalität einzubauen wäre es, einen Standard für DB-Treiber-Interfaces zu schaffen.
Ist nicht das Problem, dass sich die Interfaces je nach Treiber unterscheiden und man deshalb für die Unterstützung verschiedener DB-Systeme kaum um ein ORM herumkommt?
Ich vermute, dass es hinzugefügt wurde, weil für kleine Dienste in der Größenordnung eines persönlichen Blogs in vielen Fällen einfach SQLite völlig ausreicht. Wenn es da ist, ist es praktisch.
Ich denke, sqlite wurde aufgenommen, weil die Oberfläche am einfachsten ist und es sich gut als Referenz eignet.
Und ich weiß nicht, warum man den von Ihnen erwähnten Standard für DB-Driver-Interfaces schaffen sollte. Ich meine, etwas Ähnliches schon einmal in PHP gesehen zu haben.
Für komplexe Queries, die sich im ORM nicht abbilden lassen, verwende ich immer noch RAW-Queries ...
Sie scheinen wohl häufig mit verschiedenen DB-Typen zu arbeiten ... Wie wäre es, wenn Sie selbst eine Bibliothek schreiben? :)
Dass Laufzeiten wie Python, Java, C#, Go usw. einen Standard für DB-Driver-Interfaces bereitstellen, ist eigentlich ziemlich üblich.
Bei Node ist es dagegen so, dass sich selbst bei Treibern für dasselbe SQLite schon die Ausführung von Statements zwischen
execute()undexec()unterscheidet, sodass selbst beim bloßen Austausch des Treibers gewisse Anpassungen nötig sind.Es kommt zwar nicht oft vor, aber auch ein DB-Wechsel ist dann umständlich.
Wenn man zum Beispiel MySQL nutzt und einem nicht gefällt, was Oracle macht, oder wenn man unter den PostgreSQL-Erweiterungen etwas unbedingt Benötigtes findet und deshalb zu PostgreSQL wechselt, dann muss man bei einem Standard-Interface wie JDBC im Grunde nur das SQL validieren; im Node-Ökosystem hat man dagegen den Nebeneffekt, die gesamte DB-Aufruflogik neu aufsetzen zu müssen.
+Sie haben mir empfohlen, selbst eine Bibliothek zu bauen, aber dafür ist es deutlich einfacher, wenn es einen gemeinsamen Interface-Standard gibt.
In meiner Firma verwenden wir Java, und weil unser internes Framework MySQL, DB2, Oracle und MSSQL unterstützen muss, hat uns der JDBC-Standard bei der Wartung der datenbankspezifischen Adapter enorm geholfen.