12k
All articles

Desktop-Apps mit deno desktop erstellen

Deno desktop kompiliert TypeScript-Apps zu nativen Desktop-Binaries mit webview oder CEF, Framework-Support, Cross-Compile und Grenzen.

OpenReplay Team
OpenReplay Team
Desktop-Apps mit deno desktop erstellen

deno desktop kompiliert ein Deno-Projekt zu einer eigenständigen Desktop-App: Ihr Code, die Deno-Runtime und eine Rendering-Engine in einer einzigen Binärdatei pro Plattform. Ausgeliefert wurde das Ganze mit Deno 2.9. Was es von Electron und Tauri unterscheidet: Die Rendering-Engine ist eine Entscheidung zur Build-Zeit. Sie wählen entweder die WebView des Betriebssystems oder ein mitgeliefertes Chromium – und weder Electron noch Electrobun, Tauri oder Dioxus bieten diesen Umschalter.

Wer schon einmal eine Electron-App ausgeliefert hat, kennt die Diskussion über den 100-MB-Installer, und wer eine Tauri-App ausgeliefert hat, kennt den Bug, der sich nur unter WebKitGTK reproduzieren lässt. Diese beiden Frameworks sitzen an den entgegengesetzten Enden ein und derselben Achse, und bislang bedeutete die Wahl eines Frameworks zugleich die endgültige Festlegung auf eine Rendering-Engine.

Dies ist ein erster Blick auf die dritte Option, gerichtet an Leserinnen und Leser, die den Trade-off zwischen Electron und Tauri bereits kennen. Behandelt werden: was der Befehl erzeugt, das kleinstmögliche Programm, das das Modell verdeutlicht, was jedes Backend in Megabyte kostet, welche Framework-Projekte unverändert akzeptiert werden, wie Cross-Compilation funktioniert und was noch fehlt. Die Debatte Electron versus Tauri selbst wird in einem separaten Vergleich von Electron und Tauri behandelt.

Die wichtigsten Erkenntnisse

  • deno desktop erschien am 25. Juni 2026 mit dem stabilen Release Deno 2.9.0; der Release-Beitrag bezeichnet es weiterhin als experimentell, wobei einige Plattformfunktionen noch nicht umgesetzt sind.
  • Das Standard-Backend webview rendert über WebView2 unter Windows, WKWebView unter macOS und WebKitGTK unter Linux; das optionale cef-Backend bündelt Chromium für identisches Rendering auf jeder Plattform.
  • Denos Vergleichsseite beziffert eine WebView-basierte App auf rund 40 MB und eine CEF-basierte App auf rund 150 MB – gegenüber ~100 MB+ bei Electron und ~2–10 MB bei Tauri.
  • Ein Deno.serve()-Handler innerhalb eines Desktop-Entrypoints erhält weder Port noch Hostname; die Runtime bindet ihn an die Adresse, die das Fenster lädt.
  • --target und --all-targets ermöglichen Cross-Compilation für fünf Plattform-Triples von jedem beliebigen Host aus, ganz ohne Rust-Toolchain – mit dem macOS-.dmg als einziger hostgebundener Ausnahme.

Was ist deno desktop?

Richten Sie deno desktop auf einen Deno-Entrypoint oder auf ein Web-Framework-Projekt, und zurück kommt eine Desktop-Anwendung, die ihre Oberfläche in einer WebView zeichnet und ihre Logik in Deno ausführt. Der 2.9-Release-Beitrag stellt es als Hauptfeature vor und markiert es im selben Abschnitt als experimentell, da sich die API-Oberfläche noch stabilisiert. Es ist in der stabilen Version 2.9.0 gelandet, nicht in einem Canary-Build, wie die v2.9.0 Release Notes unter feat: deno desktop subcommand festhalten.

Drei Bestandteile fließen für jede Plattform in die Binärdatei ein: Ihr Code, die Deno-Runtime und ein Rendering-Backend. Die Kommunikation zwischen der Deno-Seite und der WebView läuft über In-Process-Channels statt über socketbasierte IPC – ein anderes Modell als Electrons Nachrichtenaustausch zwischen Main- und Renderer-Prozess. Native Oberflächen wie Deno.BrowserWindow und Deno.Tray sind in die Runtime eingebaut, sodass Fenstersteuerung und System-Tray-Icons kein Drittanbieterpaket benötigen.

Das kleinstmögliche deno-desktop-Programm

Die minimale Desktop-App besteht aus einem einzigen Deno.serve()-Handler, der HTML zurückgibt, plus einem Befehl.

// main.ts
Deno.serve(() =>
  new Response("<!DOCTYPE html><h1>Window one</h1>", {
    headers: { "content-type": "text/html" },
  })
);
deno desktop main.ts

Beachten Sie das fehlende Argument. In einem normalen Deno-Server würden Sie einen Port übergeben; hier lassen Sie ihn weg, denn in einem Desktop-Entrypoint übergibt die Runtime dem Handler die Adresse, auf die das Fenster bereits zeigt. Die kompilierte App öffnet ein natives Fenster auf diesem lokalen Server. Das ist der eine nicht offensichtliche Teil des Programmiermodells: Der HTTP-Server ist der UI-Transport, und die Runtime verdrahtet die beiden Enden für Sie.

Sollten Sie das webview- oder das cef-Backend verwenden?

Die Rendering-Engine ist eine Entscheidung zur Build-Zeit, und sie ist der Grund, warum deno desktop eine Nische besetzt, die keiner der Mitbewerber füllt. Electron bündelt ausschließlich Chromium, Tauri nutzt ausschließlich die System-WebView. deno desktop kann beides, ausgewählt über --backend oder das Feld desktop.backend in deno.json.

deno desktop main.ts                  # webview (default)
deno desktop --backend cef main.ts    # bundled Chromium

Die Backends-Seite benennt die Engines hinter dem Standard: WKWebView unter macOS, WebView2 unter Windows, WebKitGTK unter Linux. Sie dokumentiert außerdem zwei Einschränkungen dieses Backends, die für jede Evaluierung relevant sind: DevTools gibt es nur unter CEF, und WebGPU unter Linux erfordert CEF. Das cef-Backend legt eine Kopie des Chromium Embedded Framework in das App-Bundle, das dieselbe Seite allein für das Framework mit ~150 MB beziffert.

Denos Vergleichsseite führt die resultierenden App-Größen als Näherungswerte auf:

ToolEngineApp-Größe (Denos Angabe)
deno desktop, webviewOS-WebView~40 MB
deno desktop, cefGebündeltes Chromium~150 MB
ElectronGebündeltes Chromium~100 MB+
TauriOS-WebView~2–10 MB

Die Distributionsseite liefert einen weiteren Datenpunkt: Ein Hello-World auf dem WebView-Backend wiegt etwa 66 MB, und --compress drückt das auf 19 MB. Betrachten Sie all diese Werte als Denos eigene Angaben und nicht als Messungen Ihrer App.

Die Faustregel aus dem Release-Beitrag lautet: bei webview bleiben, sofern Sie nicht überall eine identische Engine benötigen. Ergänzt man das um die dokumentierten Einschränkungen, ergibt sich eine brauchbare Entscheidungsgrundlage: standardmäßig webview; wechseln Sie zu cef, wenn Ihre UI von Chromium-spezifischem Rendering abhängt, wenn Sie nicht auf allen drei OS-Engines testen können, wenn Sie während der Entwicklung DevTools benötigen oder wenn Sie WebGPU unter Linux brauchen. Der Preis des Wechsels ist die Differenz zwischen den beiden Zeilen oben.

Welche Frameworks erkennt deno desktop?

Richtet man deno desktop . auf ein bestehendes Framework-Projekt, ermittelt es anhand der Konfigurationsdatei oder der package.json, um welches Framework es sich handelt, bettet die Build-Ausgabe ein und führt den Produktionsserver des Frameworks als Deno.serve()-Handler aus. Für Next.js, Astro, Fresh und Nuxt zeigen die Framework-spezifischen Hinweise nichts weiter als den eigenen Build-Befehl des Frameworks, gefolgt von deno desktop . – ohne Adapter und ohne zusätzliche Konfiguration. SvelteKit wird ebenfalls erkannt, allerdings nur über die Ausgabe des Deno-Deploy-Adapters oder des Node-Adapters; React Router benötigt eine Deno-kompatible app/entry.server.tsx.

Führen Sie zuerst den Build des Frameworks aus. Der Befehl paketiert das, was dieser Build erzeugt hat; er stößt weder next build noch astro build für Sie an.

npx next build        # produce .next/
deno desktop .        # package the built server
deno desktop . --hmr  # development: framework dev server with hot reload

Mit --hmr zeigt das App-Fenster direkt auf den Dev-Server des Frameworks, sodass sich die Entwicklung weitgehend so anfühlt wie die Arbeit in einem Browser-Tab: Der State überlebt eine Änderung, Fast Refresh funktioniert, und Fehler erscheinen über das gewohnte Overlay.

Wie führt man Cross-Compilation von deno-desktop-Apps durch?

--target <triple> baut für eine andere Plattform und --all-targets für jede unterstützte – von jedem Host aus, ohne Rust-Toolchain. Die Distributionsseite listet fünf Targets auf: aarch64-apple-darwin, x86_64-apple-darwin, x86_64-pc-windows-msvc, aarch64-unknown-linux-gnu und x86_64-unknown-linux-gnu.

deno desktop --target x86_64-pc-windows-msvc main.ts
deno desktop --all-targets main.ts

Der Mechanismus ist Download, nicht Kompilierung. Für das angeforderte Target lädt die CLI eine fertig gebaute denort sowie ein fertig gebautes Backend-Archiv herunter und prüft beide vor der Verwendung gegen ihre SHA-256-Hashes. Genau deshalb funktioniert das dort, wo Tauri und Dioxus scheitern. Deren Rust-Toolchains müssen auf der Zielplattform kompilieren, sodass jedes Betriebssystem eine eigene Build-Maschine benötigt. Electron kann über electron-builder cross-builden, der Kontrast besteht also speziell zu den Rust-basierten Werkzeugen. Die einzige Ausnahme auf Denos Seite ist das macOS-.dmg, das hdiutil aufruft und auf einem Mac erzeugt werden muss.

Reifegrad, ehrlich betrachtet

Electron betreibt Slack, Visual Studio Code und Notion; Tauri 2 hat Jahre an Releases und Mobile-Targets hinter sich; deno desktop kam mit 2.9.0, und jedes 2.9-Patch-Release seither brachte Desktop-Fixes, einschließlich 2.9.6. Die Dokumentation benennt offen, was noch fehlt.

Bei den Ausgabeformaten ist man weiter, als die Lückenliste der Vergleichsseite vermuten lässt. Die Distributionsseite dokumentiert .app und .dmg unter macOS, ein App-Verzeichnis oder .msi unter Windows sowie ein App-Verzeichnis, .AppImage, .deb oder .rpm unter Linux, ausgewählt über die Dateiendung von --output. Die Installer .msi, .deb und .rpm wurden laut Release Notes bereits mit 2.9.0 ausgeliefert.

Die bestätigten Lücken:

  • Auto-Update unter Windows. Nur macOS und Linux schließen das Update tatsächlich ab: Sie wenden den vorbereiteten Patch an und fallen, falls die neue Version nicht startet, auf die alte zurück. Windows lädt einen Patch herunter und legt ihn bereit, tauscht ihn aber nie ein, sodass sich beim nächsten Start nichts ändert. Die Auto-Update-Seite empfiehlt, Auto-Update unter Windows vorerst als nicht unterstützt zu betrachten.
  • Notarisierung. Das Signieren läuft auf einem macOS-Host automatisch, doch der Abschnitt zum Code Signing weist darauf hin, dass Sie die Notarisierung weiterhin manuell vornehmen müssen – mit xcrun notarytool submit als eigenem Schritt.
  • Mobile. Keine iOS- oder Android-Targets, während Tauri 2 beides bietet.
  • Sicherer Speicher, Berechtigungsabfragen zur Laufzeit, gemeinsam genutzte CEF-Runtime. Die Vergleichsseite führt alle drei als fehlend oder auf der Roadmap befindlich auf; die gemeinsam genutzte Runtime wäre der Punkt, der CEF-Apps verkleinern würde – doch das ist ein Versprechen, kein Release.

Wer sollte deno desktop jetzt ausprobieren?

Probieren Sie es jetzt aus, wenn Sie ohnehin Deno einsetzen, Ihr Team TypeScript und nicht Rust schreibt und die App ein internes Werkzeug oder ein Desktop-Wrapper um eine bestehende Next.js-, Astro-, Fresh- oder Nuxt-Codebasis ist, bei dem ein 40-MB-WebView-Build akzeptabel ist und eine macOS- oder Linux-Zielgruppe das Auto-Update abdeckt. Warten Sie, wenn Sie an Windows-Nutzer ausliefern, die In-Place-Updates benötigen, wenn Sie Mobile aus derselben Codebasis brauchen oder wenn Sie eine Distributionspipeline mit jahrelang erprobtem Signing- und Installer-Tooling benötigen. Das Label „experimentell” im Release-Beitrag trifft zu: Das Modell ist solide und die Befehle funktionieren wie dokumentiert, doch die Oberfläche kann sich zwischen Patch-Releases noch verändern.

Fazit

deno desktop ist eine echte dritte Option, weil es die Entscheidung über die Rendering-Engine von der Entscheidung über das Framework trennt – und für jede Seite dieser Wahl einen dokumentierten Preis verlangt. Am günstigsten evaluieren Sie es, indem Sie deno desktop . in einem Framework-Projekt ausführen, das Sie bereits haben – einmal mit dem Standard-Backend und einmal mit --backend cef – und die beiden Artefakte gegen die oben genannten Lücken abgleichen.

FAQs

Wie ruft die WebView in einer deno-desktop-App Deno-Code auf?

Über Bindings. Auf der Deno-Seite hängen Sie mit win.bind(name, handler) einen Handler an ein Fenster; das JavaScript der Seite ruft dann bindings.name(args) auf und erhält ein Promise zurück, das den Rückgabewert des Handlers trägt. Jedes Fenster verwaltet seinen eigenen Satz von Bindings, sodass ein auf einem Deno.BrowserWindow registrierter Handler für ein anderes unsichtbar ist. Der Aufruf läuft über In-Process-Channels statt über Socket-IPC, und wenn ein Handler eine Exception wirft, erreicht die WebView ein einfaches Objekt mit name, message und stack statt eines echten Error.

Was ist das raw-Backend in deno desktop und wann sollte man es einsetzen?

Es führt eine Desktop-App ganz ohne Web-Engine aus. Fenster, Eingabeereignisse und die native API-Oberfläche bleiben erhalten, aber es gibt nichts, worin HTML gerendert werden könnte: keine WebView, keine automatische Deno.serve()-Bindung und keinen Bindings-Proxy. Es eignet sich für Apps, die ihre Oberfläche selbst mit WebGPU, Skia oder eigenem Zeichencode malen. Auswählen lässt es sich ausschließlich über das Feld desktop.backend in deno.json, da das Flag --backend nur cef und webview akzeptiert.

Kann ich eine deno-desktop-App ohne Codeänderungen zwischen dem webview- und dem cef-Backend umschalten?

Ja. Denos Backends-Seite behandelt CEF und WebView als austauschbar: Fenster, Bindings, Events, Navigation und JS-Ausführung verhalten sich bei beiden gleich, und nur das raw-Backend durchbricht diese Portabilität. Baut man für ein Backend oder Target, das man zuvor noch nicht genutzt hat, wird zunächst ein fertig gebautes Archiv heruntergeladen – im Fall von CEF einige hundert Megabyte –, per Prüfsumme verifiziert und im Deno-Cache-Verzeichnis abgelegt, sodass spätere Builds den Download überspringen.

Gelten Deno-Berechtigungen auch innerhalb einer deno-desktop-App?

Ja, allerdings stammen sie aus den in die Binärdatei einkompilierten Berechtigungen und nicht aus Abfragen. Ein Binding wird innerhalb der Deno-Runtime mit genau den Rechten ausgeführt, die dem Prozess gewährt wurden – ein Handler, der eine Datei liest, benötigt also Lesezugriff, der beim Start erteilt wurde, und nichts, was die WebView tut, kann diesen erweitern. Die Dokumentation stellt klar, dass zur Laufzeit keine separate Berechtigungsabfrage erscheint. Behandeln Sie daher alles, was ein Binding von der Seite entgegennimmt, als nicht vertrauenswürdige Eingabe und validieren Sie es.

DevTools for the frontend

Gain Debugging Superpowers

Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers.

Star on GitHub12k

We use cookies to improve your experience. By using our site, you accept cookies.