Node.js 24: Das Comeback des Jahres
Modern, sicher, schnell – und wieder „Batteries Included“
Node.js 24, seit Oktober 2025 offiziell LTS, markiert einen Wendepunkt für die JavaScript‑Runtime. Nach Jahren, in denen Bun und Deno das Innovationstempo vorgaben, zeigt Node wieder klare Richtung: moderner, sicherer, performanter – und endlich wieder mit „Batteries Included“.
Zur Einordnung: In „JavaScript, npm und Node.js 2025 – Allzweckwaffe oder veraltete Hypothek?“ habe ich das Ökosystem kritisch betrachtet. Mit Node 24 LTS beantwortet die Runtime viele dieser Punkte – praktisch und spürbar im Alltag.
⸻
Die wichtigsten Neuerungen (mit Praxisbeispielen)
1) Native Funktionen statt externer Abhängigkeiten
Glob‑Matching ist jetzt direkt in node:fs/promises verfügbar – ohne zusätzliches npm‑Paket:
// Node 24+
import { glob } from 'node:fs/promises';
const files = await glob('src/**/*.js', {
ignore: 'node_modules/**',
});
console.log(files);
Parallel bereitet das Core‑Team ein natives SQLite‑Modul vor (node:sqlite). Das reduziert Build‑/Binding‑Hürden für Tests, Prototypen oder Electron‑Apps (Status: in v24 angekündigt, Rollout gestaffelt).
⸻
2) Neue Engine, neue Power (V8 13.6)
Float16Arrayfür speichereffiziente 16‑Bit‑Floats (z. B. ML/Grafik)- Verbesserte Garbage‑Collection und geringere Startzeiten
Error.isError()für robuste Fehlerprüfungen- Unterstützung für WebAssembly Memory64 (größere Module)
RegExp.escape()zur sicheren Maskierung dynamischer Muster
// Float16Array: kompaktes Rechnen
const buf = new Float16Array(1_000);
buf[0] = 1.337;
// Fehlerprüfung
try {
throw new TypeError('kaputt');
} catch (e) {
if (Error.isError(e)) console.error('Stack:', e.stack);
}
// RegExp.escape: User‑Input sicher in RegExp einsetzen
const user = 'file.name+[v1]';
const safe = RegExp.escape(user);
const rx = new RegExp(`^${safe}$`);
console.log(rx.test('file.name+[v1]')); // true
Benchmarks (z. B. AppSignal) zeigen: Tests laufen bis zu ~40 % schneller als mit Node 20, JS‑Execution bis zu ~30 % schneller als in Node 22 (abhängig von Workload).
⸻
3) Sicherheit auf Runtime‑Ebene (Permission Model)
Das Berechtigungsmodell ist nun stabil. Mit --permission lassen sich Datei‑, Netzwerk‑ und Umgebungszugriffe granular steuern – ideal für CI/CD und sicherheitskritische Workloads.
# Beispiel: Nur Lesen im Projektverzeichnis, Schreibzugriff auf /tmp, kein Netz
node --permission \
fs=read:./,write:/tmp \
net=deny \
env=read \
app.mjs
Weitere Härtungen:
child_process.spawn()/execFile()akzeptieren nur noch Arrays als Argumente (Schutz vor Shell‑Injection)- Strengere Typprüfungen und Isolation im
vm‑Modul
⸻
4) Modernes API‑Design & Web‑APIs
- URLPattern ist global verfügbar:
const p = new URLPattern({ pathname: '/users/:id' });
const m = p.exec('https://example.com/users/42');
console.log(m?.pathname.groups.id); // "42"
- Explizites Ressourcen‑Management mit
using/await using(automatisches Aufräumen):
import { open } from 'node:fs/promises';
await using fh = await open('output.log', 'a');
await fh.writeFile('hello\n');
// fh wird am Blockende deterministisch geschlossen
- Test Runner (stabil, parallel per Default):
// node:test – keine Zusatzpakete nötig
import test from 'node:test';
import assert from 'node:assert/strict';
test('summe', () => {
assert.equal(1 + 2, 3);
});
test('subtests', async (t) => {
await t.test('a', () => assert.equal(2 * 2, 4));
await t.test('b', () => assert.rejects(async () => { throw new Error('x'); }));
});
- AsyncLocalStorage / AsyncContextFrame: performanteres asynchrones Kontext‑Tracking für Telemetrie & Tracing.
⸻
5) Unter der Haube
- npm 11: schnelleres Dependency‑Parsing, besseres Security‑Auditing, schlaueres Caching
- Undici 7 als Standard‑HTTP‑Client (moderne HTTP/2/HTTP/3‑Fähigkeiten)
- Build‑Systeme modernisiert: Windows nutzt ClangCL, macOS ≥ 13.5 vorausgesetzt
// fetch ist global – powered by Undici
const res = await fetch('https://api.example.com/data');
if (!res.ok) throw new Error(res.statusText);
const json = await res.json();
⸻
6) Module/Interop‑Verbesserungen (ESM/CJS)
- Reibungslosere Kombination von ESM und CommonJS, stabileres
dynamic import() - Besseres Tooling‑Verhalten (Stacktraces, Auflösung) beim Mischen älterer libs
// ESM‑Datei: CommonJS importieren
import { createRequire } from 'node:module';
const require = createRequire(import.meta.url);
const cjsPkg = require('legacy-cjs-lib');
// CommonJS‑Datei: ESM dynamisch importieren
(async () => {
const esm = await import('./esm-module.mjs');
esm.run();
})();
⸻
7) Performance & Startup
- Reduzierter Startup‑Overhead, flotteres
fetch()und schnelleres URL‑Parsing - Kleinere Binary‑Größe in Standard‑Builds, messbar kürzere Kaltstarts
- Async‑Kontextverwaltung (ALS) mit geringerem Overhead bei vielen Requests
⸻
8) Security & Dependency Reduction
- Core‑Module mit weniger externen Abhängigkeiten → geringeres Supply‑Chain‑Risiko
- Verbesserte Sandbox‑Optionen im
vm‑Modul, sicherere Defaults in Worker Threads - Härtungen in Prozessgrenzen und Validierungen (Argumente, Typen)
⸻
9) Permission‑Model: erweiterte Beispiele
# Standard: alles verbieten, dann selektiv erlauben
node --permission \
fs=read:./src,read:./package.json,write:/tmp \
net=allow:api.example.com:443,deny \
env=read:GITHUB_TOKEN,deny \
app.mjs
// Defensive: Prüfen, ob Zugriff erlaubt ist (Pattern)
import { access, constants } from 'node:fs/promises';
await access('src/index.ts', constants.R_OK); // wirft bei fehlender Freigabe
⸻
10) Preview: node:sqlite
Ein natives SQLite‑Modul ist für Node 24 angekündigt (gestaffelter Rollout, Stabilisierung in v25 angepeilt). Ziel: Datenbanken ohne externe Bindings/Compiler.
// Hinweis: API und Stabilität können sich ändern
// import { Database } from 'node:sqlite';
// const db = new Database('app.db');
// db.exec('CREATE TABLE IF NOT EXISTS notes (id INTEGER PRIMARY KEY, text TEXT)');
// db.prepare('INSERT INTO notes (text) VALUES (?)').run('Hallo Node 24');
⸻
Breaking Changes & entfernte Altlasten
Node 24 räumt auf – u. a. entfernt/abgekündigt:
- Alte URL‑APIs wie
url.parse()→ ersetzen durchnew URL() - TLS‑/REPL‑Altmethoden
SlowBuffer- Instanzierung bestimmter Klassen ohne
new(z. B.REPLServer) - Entferntes HTTP/2‑Feature: „Priority Signaling“ (veraltete Spezifikation)
Diese Entrümpelung erhöht Sicherheit, Wartbarkeit und ECMAScript‑Konsistenz.
⸻
Modernes Runtime‑Paradigma: „Batteries Included“
Node 24 positioniert sich wieder als Komplett‑Runtime:
- Natives
glob(), integrierter Test Runner, globalesfetch/Undici - Web‑APIs wie URLPattern,
structuredClone, Timers‑Promisify etc. - Stabilisiertes Permission‑Model, moderne V8‑Features, ESM‑Interop
Weniger externe Pakete, weniger Reibung – mehr Fokus auf Produktcode.
⸻
Migrationstipps (aus der Praxis)
- CI prüfen: Linter/Formatter/Tests mit Node 24 laufen lassen (lokal und im CI‑Image)
- URL‑Nutzung: Suchen/ersetzen von
url.parse→new URL() - Glob‑Einsatz: schrittweise Migration auf
node:fs/promises.glob - Permission Model: für Scripts/CLI klare Policies definieren (Build, Test, Deploy)
- HTTP‑Client: auf
fetch/Undici konsolidieren, doppelte Clients vermeiden - Tests: Test Runner nutzen, Parallelität aktiv halten; Subtests für Struktur
⸻
Kurz gesagt
Node.js 24 markiert den Wechsel vom minimalistischen, paketgetriebenen Ökosystem hin zur modernen Komplett‑Runtime. Es ist die erste Node‑Version seit Jahren, die nicht nur reagiert, sondern proaktiv neu definiert, was JavaScript‑Runtime 2025 bedeutet.
Ob APIs, Server oder Full‑Stack‑Apps: Node.js 24 ist das solideste Fundament seit Jahren.