Node.js 22? – Lass uns Freunde bleiben

Die neue Version 22 von Node.js ist erschreckend unspektakulär. Vielleicht ist es für mich nach 12 Jahren mit Node.js an der Zeit, die Beziehung zu beenden.

In Pocket speichern vorlesen Druckansicht 22 Kommentare lesen
Business,Partnership,Meeting,Concept.,Image,Businessmans,Handshake.,Successful,Businessmen,Handshaking

(Bild: Stella106/Shutterstock.com)

Lesezeit: 13 Min.
Von
  • Golo Roden
Inhaltsverzeichnis

Vor rund zwei Wochen, am 24. April, wurde die neue Version 22 von Node.js veröffentlicht. Daher werde ich in diesem Artikel zunächst die Neuerungen besprechen. Doch das ist nicht alles: Es wird auch um die eingeschlagene Richtung in der aktuellen Entwicklung von Node.js gehen, mit der ich persönlich nicht mehr ganz so zufrieden bin wie all die Jahre zuvor. Dass irgendwo ein Problem besteht, deutet schon der Titel dieses Artikels an: "Lass uns Freunde bleiben" ist eine Floskel, die in der Regel zwei Menschen nutzen, die sich nach einer Beziehung trennen und indirekt ausdrücken möchten, dass sie auf jeglichen weiteren Kontakt gut und gerne verzichten können.

Doch beginnen wir zunächst mit den Fakten. Node.js 22 ist offensichtlich eine gerade Versionsnummer, was bedeutet, dass diese Version im kommenden Oktober zur neuen LTS-Version (Long-Term Support) werden wird. Und was bietet diese neue Version? Um es kurz zu machen: Ich persönlich empfinde Node.js 22 als extrem unspektakulär, und das meine ich leider nicht im positiven Sinne. Denn Neuerungen muss man buchstäblich mit der Lupe suchen, und das, was dann tatsächlich neu ist, ist entweder uninteressant oder schon dermaßen lange überfällig, dass es mir schwerfällt, dafür noch Begeisterung aufzubringen.

the next big thing – Golo Roden

Golo Roden ist Gründer und CTO von the native web GmbH. Er beschäftigt sich mit der Konzeption und Entwicklung von Web- und Cloud-Anwendungen sowie -APIs, mit einem Schwerpunkt auf Event-getriebenen und Service-basierten verteilten Architekturen. Sein Leitsatz lautet, dass Softwareentwicklung kein Selbstzweck ist, sondern immer einer zugrundeliegenden Fachlichkeit folgen muss.

Bitte verstehen Sie mich dabei nicht falsch: Es ist grundsätzlich natürlich erfreulich, dass die Entwicklung von Node.js mit der neuen Version wieder einen kleinen Schritt vorangeht, doch angesichts der aktuellen Entwicklungen bei Deno und Bun habe ich gewisse Bedenken, was die Zukunft von Node.js betrifft. Doch was genau sind diese unspektakulären Neuerungen?

Empfohlener redaktioneller Inhalt

Mit Ihrer Zustimmmung wird hier ein externes YouTube-Video (Google Ireland Limited) geladen.

Ich bin damit einverstanden, dass mir externe Inhalte angezeigt werden. Damit können personenbezogene Daten an Drittplattformen (Google Ireland Limited) übermittelt werden. Mehr dazu in unserer Datenschutzerklärung.

Als Erstes ist zu erwähnen, dass Node.js nun über einen Watch-Mode verfügt und außerdem Websockets nativ unterstützt. Wenn Sie jetzt stocken, weil Sie dachten, dass es beides in Node.js bereits gab, dann liegen Sie richtig: Beide Features waren schon früher vorhanden, der Watch-Mode seit Version 19, Websockets hingegen seit Version 21. Neu ist daher eigentlich nur, dass die beiden Features nicht mehr als experimentell, sondern als stabil gekennzeichnet sind. Beides ist grundsätzlich auch erfreulich, stellt jedoch kaum eine bahnbrechende Neuerung dar, insbesondere, da beides seit Jahren überfällig war.

Zum Thema experimentelle Features: Tatsächlich neu ist, dass man Skripte aus der package.json, die bisher über npm run ausgeführt wurden, jetzt auch über node --run starten kann. Das verbessert geringfügig die Performance beim Starten des jeweiligen Skriptes, aber abgesehen davon würde ich auch hier sagen: Ganz nett, aber nichts Weltbewegendes. Am interessantesten ist dabei vielleicht noch der Aspekt, dass die Skripte aus der package.json auf dem Weg unabhängig von npm werden, sodass der Aufruf auch mit anderen Paketmanagern konsistent funktioniert.

Zwei weitere neue Features sind ein vergrößerter interner Puffer für Streams und endlich die Unterstützung für Globs im fs-Modul. Aber auch hier gilt, dass diese Features nett sind, aber dass man auch weiterhin gut ohne sie ausgekommen wäre. Bis zu diesem Punkt, denke ich, werden Sie mir zustimmen, die Neuerungen in Node.js 22 sind eher überschaubar und tatsächlich sehr unspektakulär.

Damit kommen wir zum einzigen Feature, das tatsächlich nicht ganz so unspektakulär ist, das aber meiner persönlichen Meinung nach ungefähr fünf Jahre zu spät kommt: Ab Node.js 22 ist es nämlich möglich, zumindest experimentell, ein ESM-Modul per require zu laden. Bisher ging das nicht, und es stellte sich stets die Frage, wann man die eigene Anwendung am besten auf ESM umstellen solle beziehungsweise ab wann man ESM-basierte Module verwenden könne.

Dieses Problem erübrigt sich nun weitestgehend. Denn mit der neuen Fähigkeit wird endlich der Mischbetrieb von CommonJS und ESM möglich. Das ist grundsätzlich eine begrüßenswerte Sache, spielt aber in der Praxis kaum noch eine Rolle, weil sich ESM inzwischen (nicht zuletzt dank TypeScript) weit verbreitet und etabliert hat. Das Problem, das damit gelöst wird, war vor ein paar Jahren weitaus relevanter, als es das heute ist. Denn inzwischen funktioniert das Meiste problemlos mit ESM. Insofern ist das Feature beachtlich, nur kommt es, wie gesagt, ein paar Jahre zu spät.

Und das war’s. Das ist Node.js 22.

Ich habe vorhin bereits Deno und Bun angesprochen. Wer meine Arbeit näher verfolgt, weiß, dass ich Deno und Bun eher skeptisch gegenüberstehe. Dennoch kann man nicht abstreiten, dass beide Projekte frischen Wind in die gesamte JavaScript-Welt bringen. Node.js hingegen hinkt seit vielen Versionen mehr schlecht als recht hinterher: Es fehlt immer noch ein integrierter Linter. Es fehlt ein integrierter Formatter. Zwar gibt es inzwischen einen Compiler, aber der ist derart umständlich zu benutzen, dass ihn praktisch niemand verwendet. Immer noch fehlt eine vernünftige Unterstützung für TypeScript. Es fehlt eine umfangreiche, auf Sandboxing basierende Sicherheitslösung. Es fehlt immer noch Unterstützung für JSX, geschweige denn für TSX. Und so weiter.

Und das ist irgendwie ein wenig dürftig. Mir ist klar, dass es viel einfacher ist, all diese Dinge in einem neuen Projekt einzubauen, als sie in einer bestehenden Codebasis nachzuziehen, aber trotzdem frage ich mich: Was ist denn bei Node.js in den vergangenen drei Jahren eigentlich überhaupt passiert? Denn den Eindruck, dass die jeweils neue Version nicht so viel zu bieten hat ist, habe ich leider nicht zum ersten Mal, sondern offen gestanden schon zum inzwischen fünften Mal in Folge!

Das hat nun im Laufe der Zeit dazu geführt, dass ich mich gedanklich schrittweise von Node mehr und mehr verabschiedet habe. Ich fühle mich inzwischen deutlich wohler bei Go und arbeite damit weitaus effizienter und produktiver.

Wer mich schon länger kennt, könnte mich nun kritisieren und mir vorwerfen: "Aber du bist doch die vergangenen zehn Jahre durch die Gegend gerannt und hast Node als die beste Erfindung seit der Erfindung von geschnittenem Brot angepriesen!" – und das wäre richtig. Sie könnten sogar noch einen Schritt weitergehen und sagen: "Und davor waren es zehn Jahre lang C# und .NET!" – und auch das wäre richtig. Aber ich habe momentan das Gefühl, dass ich mich, ähnlich wie ich mich um 2010 von C# und .NET verabschiedet habe, aktuell gedanklich auch von Node verabschiede.

Doch woran liegt das? Warum war ich zweimal für rund zehn Jahre mit einer Technologie sehr glücklich, und dann kam mehr oder weniger plötzlich der große Bruch? Liegt das an den Technologien selbst? Liegt es an mir? Was ist der Grund dafür? Um bei den Floskeln zu bleiben, könnte ich nun sagen: "Es liegt nicht an Dir, es liegt an mir." Doch ist das wirklich so?

Selbstverständlich habe ich mich weiterentwickelt und verändert, doch das gilt auch für die jeweiligen Technologien. C# und .NET waren um das Jahr 2010 nicht mehr dasselbe wie zehn Jahre zuvor, und auch Node.js hat sich in den vergangenen zehn Jahren weiterentwickelt. Nun stellt sich die Frage: Wie bewertet man das? Ich persönlich greife gerne auf eine sehr einfache Metrik zurück, um Technologien zu beurteilen. Ich frage mich nämlich, inwiefern die folgende Aussage zutrifft: "Make simple things simple, and complex things possible."

Meine Erfahrung zeigt mir, dass sich langfristig jene Technologien durchsetzen, die beides erfüllen – die also eine niedrige Einstiegshürde bieten und bei komplexen Anliegen nicht im Weg stehen. Genau das war um das Jahr 2000 herum der Grund, warum mich C# und .NET bereits mit der ersten Betaversion so begeistert haben. Sie waren viel einfacher zugänglich als zum Beispiel C++, aber zugleich weitaus mächtiger als Visual Basic. Sie waren simpler und boten gleichzeitig sehr viele Möglichkeiten. C# hat für mich damals die Anforderung "make simple things simple" definitiv erfüllt und mir im Vergleich zu dem, was ich zuvor gemacht hatte, ein ganzes Universum eröffnet. Insofern wurde "make complex things possible" ebenfalls erfüllt.

Doch C# und .NET haben (für mein Empfinden) leider nicht mit dem Zeitgeist Schritt gehalten, und um das Jahr 2010 kamen immer mehr Themen auf, bei denen ich nicht mehr das Gefühl hatte, dass diese beiden Anforderungen noch erfüllt waren. Das betraf insbesondere den Schritt in die Cloud und einige Jahre später dann auch das Thema Containerisierung – bei beiden hat sich Microsoft lange Zeit äußerst schwergetan.

Das Ergebnis: C# und .NET wirkten zunehmend schwerfälliger, umständlicher, komplexer und träger, und das hat mir damals immer weniger zugesetzt. In dieser Zeit kam ich mit Node.js in Berührung, das das genaue Gegenteil davon war: Klein, kompakt, leichtgewichtig und schnell. Es war so viel einfacher und effizienter, Web- und Cloud-APIs mit Node.js zu entwickeln als mit ASP.NET, dass Node.js für mich der logische nächste Schritt war. Es hat "simple things" wieder "simple" gemacht und mir weit mehr Möglichkeiten geboten, auch "complex things" umzusetzen, weil Node im Vergleich zum damaligen (!) ASP.NET viel einfachere Möglichkeiten bot, nah am HTTP-Protokoll zu agieren.

Doch wie sieht die Entwicklung mit Node heutzutage aus? Zunächst benötigt man eine Myriade an Werkzeugen, selbst um ein einfaches Basis-Setup zu erhalten: TypeScript, ESLint, Prettier, Mocha, eine ganze Reihe von passenden Plug-ins, die passenden Regeln, alles will konfiguriert werden, vielleicht noch einen Bundler, und, und, und. Dann gab es jahrelang das Theater mit CommonJS versus ESM, der fehlenden oder mangelhaften Unterstützung durch diverse Tools, und so weiter.

Das entspricht einfach nicht mehr meiner Vorstellung von "make simple things simple". Zugegebenermaßen ist das im Backend nicht ganz so schlimm wie im Frontend, aber ein einfaches Hallo-Welt mit zeitgemäßem Tooling ist inzwischen leider ein ziemlicher Aufwand geworden.

Und hier schließt sich dann der Kreis zu dem, was ich vorhin geschrieben habe: Ja, ich bin kein allzu großer Freund von Deno und Bun, aber beide Projekte bringen die Developer-Experience für JavaScript auf einen Stand, der dem Jahr 2024 angemessen ist. Node.js hingegen hinkt nicht nur ein paar Schritte, sondern ganze Kilometer hinterher, und es passiert schlichtweg zu wenig. Deno und Bun zeigen, wie es laufen könnte: TypeScript ist integriert, ein Formatter ist integriert, ein Linter ist integriert, ein Compiler, der einfach zu benutzen ist und gut funktioniert, ist integriert, ebenso die Installation als Single-Binary und so weiter.

Das alles nützt jedoch nichts, wenn man nicht auf Deno oder Bun wechseln, sondern beim Platzhirsch bleiben möchte. Ich habe nun mehrere Jahre darauf gewartet, dass bei Node.js etwas Wesentliches in dieser Richtung passiert. Und es gibt zwar erste Schritte, zum Beispiel mit dem inzwischen integrierten Test-Runner, aber das ist im Vergleich so wenig, dass ich mich langsam frage, ob diese Richtung überhaupt noch weiterverfolgt wird.

Hinzu kam dann bei uns im Unternehmen noch die Anforderung, Software nicht im Quellcode auszuliefern, sondern als Binärpakete. Das ist einer der Gründe, warum wir bei Go gelandet sind: Dort gibt es einen echten Compiler, der Binärcode erzeugen kann. Darüber hinaus hat Go noch einiges mehr zu bieten, das uns überzeugt hat – wie wir auch ausführlich dokumentiert haben. Und: Go bietet all das von Haus aus. Zudem ist die Sprache sehr viel einfacher und klarer gehalten, es gibt nicht zig verschiedene Konzepte für asynchronen Code, es gibt auch sonst nicht zig verschiedene Wege für sonst etwas, sondern Go ist im Vergleich zu JavaScript extrem geradlinig.

Und damit landen wir genau wieder bei "make simple things simple, and complex things possible". Dieses Kriterium erfüllt Go für mich heute in viel stärkerem Maße als Node, und deswegen tue ich mir inzwischen mit Node so schwer. Natürlich weiß ich nicht, ob das vielleicht in weiteren zehn Jahren nicht auch wieder anders aussehen wird. Das muss ich einfach abwarten. Aber das ist zumindest meine Erklärung dafür, warum ich mich nach einer Phase der großen Begeisterung inzwischen nicht mehr so richtig für Node (und davor auch für C# und .NET) erwärmen kann. Man könnte sagen: Wir haben uns auseinandergelebt. (map)