Deno erklärt: Die sichere JavaScript-Laufzeit neben Node.js

Berechtigungen, TypeScript ohne Build-Schritt und npm-Kompatibilität: was Deno anders macht und wann sich der Umstieg lohnt
Aktualisiert:
Abstract
- #Deno
- #Node.js
- #JavaScript
- #TypeScript
- #Webentwicklung
- #serverseitiges JavaScript
- #JSR
- #npm
Der Node.js-Erfinder hat noch einmal von vorn angefangen. Was ist daraus geworden?
Ein Skript, das eine CSV-Datei einlesen soll, öffnet heimlich eine Netzwerkverbindung und schickt Umgebungsvariablen samt API-Schlüsseln an einen fremden Server. Unter Node.js fällt das niemandem auf, denn jedes Programm darf dort alles, was der angemeldete Benutzer darf. Unter Deno bricht das Skript ab und fragt nach: Netzzugriff wurde nie erlaubt.
Diese Grundidee, dass Code nur darf, was man ihm ausdrücklich gestattet, unterscheidet Deno bis heute am deutlichsten von Node.js. Als dieser Beitrag 2020 erstmals erschien, stand Deno kurz vor Version 1.0 und galt als radikaler Neuanfang ohne npm. Inzwischen ist Deno 2 erschienen, versteht package.json und npm-Pakete und hat sich vom Gegenentwurf zu einer ernsthaften Alternative entwickelt. Was Deno heute ist, wie es funktioniert und für wen es sich lohnt, erklärt der folgende Überblick.
Warum Ryan Dahl eine zweite Laufzeit gebaut hat
Deno stammt von Ryan Dahl, der 2009 auch Node.js geschaffen hat. 2018 hielt er auf der JSConf EU einen viel beachteten Vortrag über Designentscheidungen, die er bei Node.js bereute: das fehlende Sicherheitsmodell, den zentralen Ordner node_modules, die Paketauflösung über package.json und den Verzicht auf Promises in den frühen Kern-APIs. Deno war seine Antwort darauf, wie eine serverseitige JavaScript-Laufzeit aussehen würde, wenn man mit dem Wissen von zehn Jahren noch einmal anfinge.
Technisch setzt Deno wie Node.js auf V8, die JavaScript-Engine von Chrome. Der Rest ist in Rust geschrieben, nicht in C++. Version 1.0 erschien im Mai 2020. Hinter dem Projekt steht heute die Firma Deno Land Inc., die neben der quelloffenen Laufzeit (MIT-Lizenz) auch den Hosting-Dienst Deno Deploy betreibt.
Eine Laufzeitumgebung ist dabei das Programm, das JavaScript außerhalb des Browsers ausführt und ihm Zugriff auf Dateien, Netzwerk und Betriebssystem gibt. Node.js, Deno und Bun spielen alle in dieser Liga, setzen aber unterschiedliche Schwerpunkte.
Was Deno anders macht als Node.js
Sicherheit durch ausdrückliche Berechtigungen
Ein Deno-Programm startet in einer Art Sandkasten. Ohne Freigabe darf es weder Dateien lesen noch schreiben, keine Netzwerkverbindungen öffnen, keine Umgebungsvariablen lesen und keine anderen Programme starten. Die Rechte vergeben Sie beim Start über Flags, und zwar so fein, wie Sie möchten:
# Nur Lesezugriff auf das Verzeichnis ./daten und Netzzugriff auf eine Domain
deno run --allow-read=./daten --allow-net=api.example.com import.ts
Fehlt eine Berechtigung, fragt Deno im Terminal nach oder bricht ab. Für Teams ist das vor allem beim Umgang mit fremdem Code interessant. Ein kompromittiertes Paket, das Zugangsdaten abgreifen will, scheitert an der fehlenden Netzfreigabe. Ein vollständiger Schutz ist das nicht: Wer pauschal --allow-all (kurz -A) setzt, verschenkt den Vorteil, und viele Werkzeuge verlangen breite Rechte. Node.js hat inzwischen ein eigenes Permission Model nachgerüstet, das aber standardmäßig ausgeschaltet ist.
TypeScript ohne Build-Schritt
Deno führt TypeScript-Dateien direkt aus. Sie brauchen weder eine tsconfig.json noch einen separaten Compiler-Aufruf. Die Typprüfung übernimmt deno check, auf Wunsch auch automatisch vor dem Start. Neuere Node.js-Versionen können TypeScript inzwischen ebenfalls ausführen, indem sie die Typannotationen einfach entfernen (Type Stripping). Bei Deno ist die Unterstützung aber älter, vollständiger und ohne Einschränkungen bei Sprachmitteln wie enum.
Werkzeuge aus einer Hand
Wer ein Node.js-Projekt aufsetzt, installiert typischerweise Prettier, ESLint, ein Test-Framework und einen Bundler und pflegt deren Konfigurationen. Deno bringt die wichtigsten Werkzeuge im selben Programm mit:
deno fmtformatiert Code,deno lintprüft ihn auf typische Fehler,deno testführt Tests aus und misst auf Wunsch die Testabdeckung,deno taskstartet Projektskripte, ähnlich wienpm run,deno compileerzeugt eine eigenständige ausführbare Datei, die ohne installierte Laufzeit läuft.
Das senkt die Einstiegshürde spürbar. Angenommen, ein Mittelständler möchte ein internes Hilfsskript als einzelne Datei an Kolleginnen in der Buchhaltung verteilen: Mit deno compile entsteht ein Programm, das sich ohne Node-Installation starten lässt.
Webstandards statt eigener APIs
Deno orientiert sich konsequent an Schnittstellen, die auch im Browser existieren: fetch, Request, Response, URL, Web Streams und Web Crypto. Code, der nur diese APIs nutzt, läuft oft ohne Änderung im Browser, in Deno und in Edge-Umgebungen wie Cloudflare Workers. Top-Level-await, also await außerhalb einer async-Funktion, funktioniert in Deno von Anfang an, weil Deno auf ES-Module ausgelegt ist.
Deno in der Praxis: drei kurze Beispiele
Daten abrufen mit Top-Level-await
Ein Skript, das Daten von einer API lädt, kommt mit wenigen Zeilen aus:
// abruf.ts – benötigt Netzzugriff auf api.github.com
const antwort = await fetch('https://api.github.com/users/denoland');
const daten = await antwort.json();
console.log(
`${daten.name} hat ${daten.public_repos} öffentliche Repositories.`,
);
Gestartet wird es mit deno run --allow-net=api.github.com abruf.ts. Ohne die Freigabe verweigert Deno die Verbindung.
Ein HTTP-Server mit Deno.serve
Die ursprüngliche Fassung dieses Beitrags zeigte einen Server mit der Funktion serve aus der damaligen Standardbibliothek. Diese ist inzwischen abgelöst; heute ist der Server direkt in die Laufzeit eingebaut:
// server.ts – starten mit: deno run --allow-net server.ts
Deno.serve({ port: 8000 }, (anfrage: Request): Response => {
const url = new URL(anfrage.url);
if (url.pathname === '/status') {
return Response.json({ status: 'ok', zeit: new Date().toISOString() });
}
return new Response('Hallo aus Deno', {
headers: { 'content-type': 'text/plain; charset=utf-8' },
});
});
Die Funktion bekommt ein Standard-Request-Objekt und gibt eine Response zurück, genau wie ein Service Worker im Browser. Für größere Anwendungen gibt es Frameworks wie Hono, Oak oder Fresh, das Web-Framework des Deno-Teams.
Tests ohne Zusatzpaket
Tests schreiben Sie mit Deno.test und Hilfsfunktionen aus der Standardbibliothek:
// rechnung_test.ts – starten mit: deno test
import { assertEquals } from 'jsr:@std/assert';
function bruttoBetrag(netto: number, steuersatz = 0.19): number {
return Math.round(netto * (1 + steuersatz) * 100) / 100;
}
Deno.test('Bruttobetrag mit 19 Prozent', () => {
assertEquals(bruttoBetrag(100), 119);
});
Deno.test('Bruttobetrag mit 7 Prozent', () => {
assertEquals(bruttoBetrag(100, 0.07), 107);
});
Pakete: von URL-Imports zu JSR und npm
Der größte Wandel seit 2020 betrifft die Paketverwaltung. Ursprünglich setzte Deno allein auf Importe über vollständige URLs, etwa von deno.land/x. Das war elegant, aber unpraktisch: Versionen steckten verstreut in Importzeilen, und das riesige npm-Ökosystem blieb weitgehend außen vor. Genau das bremste die Verbreitung.
Heute gibt es drei Wege, Code einzubinden:
- JSR (JavaScript Registry), eine 2024 vom Deno-Team gestartete Paketregistry, die TypeScript-Quellcode direkt veröffentlicht und auch von Node.js, Bun und anderen Laufzeiten aus nutzbar ist. Die Deno-Standardbibliothek liegt dort unter
@std. - npm-Pakete über den Präfix
npm:, zum Beispielimport express from 'npm:express@5';. Deno lädt die Pakete in einen globalen Cache und kann auf Wunsch auch einen lokalennode_modules-Ordner anlegen. - Node-Kernmodule über den Präfix
node:, etwaimport { readFile } from 'node:fs/promises';.
Abhängigkeiten verwalten Sie zentral in der Datei deno.json, die auch Tasks und Formatierregeln aufnimmt:
{
"tasks": {
"dev": "deno run --watch --allow-net server.ts",
"test": "deno test"
},
"imports": {
"@std/assert": "jsr:@std/assert@^1.0.0",
"hono": "jsr:@hono/hono@^4.0.0"
}
}
Mit deno add jsr:@std/assert oder deno add npm:zod trägt Deno neue Pakete selbst ein. Seit Deno 2 versteht die Laufzeit zudem eine vorhandene package.json. Viele Node.js-Projekte lassen sich damit testweise unter Deno starten, ohne sie umzubauen. Wer tiefer in den Hintergrund der Modulsysteme einsteigen möchte, findet ihn im Beitrag über den Weg von CommonJS zu ESM.
Deno, Node.js oder Bun: eine Einordnung
Mit Bun ist seit 2023 eine dritte große Laufzeit hinzugekommen, die vor allem mit Geschwindigkeit wirbt. Wie sich Bun im Detail schlägt, beschreibt der Beitrag Bun.js als Alternative zu Node.js. Grob lassen sich die drei so einordnen:
| Kriterium | Node.js | Deno | Bun |
|---|---|---|---|
| Sicherheitsmodell | Permission Model, standardmäßig aus | Berechtigungen standardmäßig aktiv | keines vergleichbarer Art |
| TypeScript | Type Stripping in neueren Versionen | direkt, mit Typprüfung per deno check | direkt, mit Typprüfung per bun check |
| Mitgelieferte Werkzeuge | Test-Runner, sonst Fremdpakete | Formatter, Linter, Tests, Compiler | Paketmanager, Tests, Bundler, Formatter |
| npm-Kompatibilität | vollständig | hoch, nicht lückenlos | hoch, nicht lückenlos |
| Reife und Verbreitung | sehr hoch | mittel | jünger |
Bei der Geschwindigkeit sind Benchmarks der Hersteller mit Vorsicht zu lesen. Für typische Webanwendungen, die auf Datenbanken und externe Dienste warten, entscheidet die Laufzeit selten über die Antwortzeit. Wichtiger sind Stabilität, Kompatibilität mit den benötigten Paketen und die Erfahrung im Team.
Node.js hat in den vergangenen Jahren viele Ideen aufgegriffen, die Deno vorgemacht hat: einen eingebauten Test-Runner, fetch, ein Rechtesystem und das Ausführen von TypeScript. Der Abstand ist dadurch kleiner geworden. Einen Überblick über die Entwicklung aller drei Laufzeiten gibt der Beitrag JavaScript 2026: Bun, Deno und TypeScript 7.
Wann sich Deno für Ihr Team lohnt
Unsere Einschätzung: Deno ist ausgereift genug für den produktiven Einsatz, aber kein Grund, funktionierende Node.js-Anwendungen umzuschreiben.
Gute Einsatzfelder sind neue, überschaubare Dienste und Werkzeuge:
- interne Skripte und Kommandozeilenwerkzeuge, die sich mit
deno compileals einzelne Datei verteilen lassen, - kleine APIs und Webhooks, bei denen das Rechtesystem den Schaden durch fehlerhafte Abhängigkeiten begrenzt,
- Projekte, die ohnehin vollständig in TypeScript entstehen und von wenig Konfiguration profitieren,
- Edge-Funktionen, die auf Webstandards setzen und auch anderswo laufen sollen.
Zurückhaltung empfiehlt sich bei großen Bestandsanwendungen mit vielen Abhängigkeiten, bei Paketen mit nativen Erweiterungen und überall dort, wo Hosting, Monitoring und Betrieb fest auf Node.js zugeschnitten sind. Auch die Frage nach Fachkräften spielt eine Rolle: Node.js-Erfahrung ist am Arbeitsmarkt deutlich verbreiteter.
Ein pragmatischer Weg ist ein Pilotprojekt. Angenommen, ein Entwicklungsteam braucht einen kleinen Dienst, der nachts Bestelldaten aus einem Webshop abholt und als CSV ablegt. Ein solcher Dienst ist schnell in Deno geschrieben, berührt keine kritischen Systeme und zeigt nach einigen Wochen, ob Werkzeuge, Pakete und Betrieb zum Team passen.
Wer Backend-Projekte mit TypeScript plant und Laufzeit, Architektur und Werkzeuge sauber auswählen möchte, findet auf unserer Seite zu TypeScript und Node.js für APIs und Microservices Beratung, Coaching und Seminare zu diesen Themen.
Häufige Fragen zu Deno
Lässt sich ein bestehendes Node.js-Projekt einfach mit Deno starten?
Oft ja, zumindest zum Ausprobieren. Seit Deno 2 werden package.json, node_modules und CommonJS-Module weitgehend unterstützt. Lücken gibt es vor allem bei Paketen mit nativen Add-ons und bei Werkzeugen, die tief in Node.js-Interna greifen. Ein Testlauf mit der vollständigen Testsuite zeigt schnell, wo es hakt.
Ist Deno schneller als Node.js?
Pauschal lässt sich das nicht sagen. In einzelnen Benchmarks liegt mal die eine, mal die andere Laufzeit vorn, und Herstellerzahlen messen meist günstige Szenarien. Für die meisten Geschäftsanwendungen ist der Unterschied unerheblich. Wenn Leistung kritisch ist, hilft nur ein Vergleich mit Ihrem eigenen Code und realistischer Last.
Braucht man für Deno noch npm?
Nein. Deno lädt npm-Pakete selbst über den Präfix npm: oder aus einer package.json. Ein separater Aufruf von npm install ist nicht nötig.
Ist Deno kostenlos?
Die Laufzeit selbst ist Open Source unter der MIT-Lizenz und kostenlos. Kostenpflichtig können Zusatzdienste des Herstellers sein, etwa höhere Kontingente bei Deno Deploy. Deno-Anwendungen lassen sich aber genauso in Docker-Containern auf eigener Infrastruktur oder bei beliebigen Cloud-Anbietern betreiben.