Deno bringt `deno desktop` mit: WEF-basierter Unterbefehl für eigenständige Desktop-Apps mit Deno.BrowserWindow, vereinten DevTools und Cross-Compile für macOS, Windows und Linux

Deno bringt `deno desktop` mit: WEF-basierter Unterbefehl für eigenständige Desktop-Apps mit Deno.BrowserWindow, vereinten DevTools und Cross-Compile für macOS, Windows und Linux

lschvn

Deno hat deno desktop am 16. Juni 2026 zusammengeführt (PR #33441, ursprünglich im April 2026 als Issue #3234 eröffnet), einen neuen Unterbefehl, der ein Deno-Projekt in eine eigenständige Desktop-Anwendung kompiliert. Am selben Morgen landeten auch drei kleinere PRs: deno link / deno unlink für das links-Array in deno.json, deno test --shard zum Aufteilen eines Testlaufs auf mehrere Maschinen und ein fetch request_builder_hook für Cloud-Deployments. Die Schlagzeile ist der Desktop-Unterbefehl: Er gibt Deno einen erstklassigen Pfad, mit einer einzigen deno desktop <entry>-Invocation plattformübergreifende Desktop-Apps auszuliefern, und die Implementierung ist der größte einzelne Zusatz zur Deno-CLI seit Deno 2.7 die Temporal-API und Windows-on-Arm-Builds stabilisiert hat.

Was deno desktop tatsächlich tut

deno desktop <entry> kompiliert ein Deno-Projekt in eine eigenständige Desktop-Anwendung, die auf WEF (WebView Engine Foundation) aufsetzt. Die CLI lädt vorgebaute WEF-Backends von github.com/denoland/wef/releases, pinnt die Version über die Cargo.lock des Projekts, verifiziert sie per SHA-256 und legt sie unter <deno_dir>/wef/<version>/ ab. Für die Entwicklung gegen einen lokalen WEF-Checkout zeigt WEF_DEV_DIR die CLI auf ein lokales Verzeichnis statt herunterzuladen.

Es gibt drei Backends, pro Projekt wählbar:

  • cef, der Default, ein gebündeltes Chromium (CEF ist die gleiche Engine-Familie, auf der der Electron-Renderer aufsetzt).
  • webview, der Webview des Host-Betriebssystems (Edge WebView2 auf Windows, WKWebView auf macOS, WebKitGTK auf Linux).
  • raw, ein winit-Fenster ohne eingebettete Engine, für Projekte, die selbst in das Fenster zeichnen wollen.

Deno.serve() im Entry bindet sich automatisch an den Port, zu dem der Webview navigiert, über eine neue DENO_SERVE_ADDRESS-Umgebungsvariable, die die Desktop-Runtime injiziert. Ein Framework-Projekt kann seine normale port-Konfiguration behalten und das Binding der Desktop-Runtime überlassen.

Framework-Auto-Erkennung und HMR

Die CLI erkennt Framework-Projekte in cli/tools/framework.rs automatisch, mit erstklassiger Unterstützung für Next.js, Astro, Fresh, Remix, Nuxt, SvelteKit, SolidStart, TanStack Start und Vite SSR. Ein erkanntes Framework-Projekt bekommt standardmäßig den Produktionsserver des Frameworks; unter --hmr läuft stattdessen der Dev-Server des Frameworks (Next-Dev-Server für Next, Nuxt-Dev-Server für Nuxt, Vite-Dev-Server für Vite SSR usw.).

Nicht-Framework-Projekte bekommen unter --hmr trotzdem Hot-Reload, aber über einen anderen Mechanismus. Die CLI nutzt einen File-Watcher plus einen CDP-Debugger.setScriptSource-Hot-Swap, um Änderungen in das laufende V8-Isolat zu schieben, während die Deno-Runtime und der CEF-Prozess am Leben bleiben. Der praktische Effekt ist derselbe: Datei editieren, Änderung sehen, das Fenster lädt nicht neu. Die Asymmetrie ist, dass Framework-Projekte die HMR-Pipeline des Frameworks bekommen, die normalerweise granularer ist (Component-scoped Updates, Fast-Refresh-Grenzen, Framework-Level-State-Preservation), während Nicht-Framework-Projekte einen V8-Script-Level-Hot-Swap bekommen. Der Trade-off ist in der PR dokumentiert: Icon-Sets werden im --hmr-Modus noch nicht unterstützt, nur ein einzelner Icon-Pfad funktioniert in diesem Modus.

Deno.BrowserWindow und die native API-Oberfläche

Die neue Deno.BrowserWindow-API (deklariert in cli/tsc/dts/lib.deno.desktop.d.ts) ist das, was Nutzercode aufruft, um ein Fenster zu steuern. Die Oberfläche deckt den Fenster-Lebenszyklus ab (show / hide / focus / close / reload), Größe und Position, alwaysOnTop, Navigation, App- und Kontextmenüs, native Fenster-Handles sowie Keyboard-, Maus-, Wheel-, Resize- und Fokus-Events. Zwei nur-native Module gesellen sich dazu: Deno.dock (nur macOS) für die Dock-Tile-Integration und Deno.Tray (plattformübergreifend) für Statusbereich-Icons mit Tooltips, Dark-Mode-Varianten und Kontextmenüs.

Ein bind-/unbind-RPC-Kanal legt das JavaScript des Webview auf der Deno-Seite als bindings.<name>() offen, und die umgekehrte Richtung ist executeJs von Deno in den Webview. Die Runtime-Integration ist der Teil, der den meisten Hebel auf bestehenden JS-Code hat: prompt(), alert() und confirm() im Webview werden zu nativen Popups, und ungefangene Fehler zeigen einen nativen Alert mit optionalem POST an desktop.errorReporting.url für Crash-Reporting. Der Auto-Updater legt Deno.desktopVersion und ein Deno.autoUpdate({ url, interval, onUpdateReady, onRollback }) offen, das <url>/latest.json pollt, bsdiff-Patches auf die Dylib anwendet (über qbsdiff), das Ergebnis für den nächsten Start staged und bei einem fehlgeschlagenen Start einen Rollback macht.

Eine DevTools-Session, zwei V8-Isolate

Die Flags --inspect, --inspect-brk und --inspect-wait laufen über einen neuen CDP-Multiplexer in cli/tools/desktop_devtools.rs, der die Deno-Runtime-V8 und die CEF-Renderer-V8 als zwei angehängte Targets in einer einzigen DevTools-Session anzeigt. Der Effekt für den Nutzer ist ein einziges Console-Dropdown (Renderer / Deno) und ein einziges Sources-Panel mit beiden Threads. Der Multiplexer spricht Chrome DevTools Protocol zum Inspector-Client und multiplexiert es auf zwei Backends, eine CDP-Verbindung zur V8 der Runtime und eine zur V8 des Renderers.

--inspect-brk pausiert beide Isolate beim Start (Deno über seinen eigenen Mechanismus, CEF über ein injiziertes Debugger.enable + Debugger.pause vor der Navigation). Für die meisten Desktop-Debug-Sessions ist das der Workflow: Beide pausieren, Breakpoint im Renderer setzen, Breakpoint in der Runtime setzen, Unpause, die App treiben, zwischen Threads im selben Sources-Panel steppen. Das CEF-Target ist dasselbe DevTools-Target, das Chromium nutzt, einschließlich derselben Performance-, Memory- und Network-Panels; das Deno-Target ist das Standard-Deno-V8-Target mit deno_core-Introspection.

Cross-Compile und Distribution

Die Flags --target und --all-targets laden vorgebaute denort-Binaries und WEF-Backends für das Ziel-Triple herunter. Die Outputs sind:

  • macOS: ein .app-Bundle (Framework unter Contents/Frameworks/), mit .dmg produziert via hdiutil.
  • Windows: eine .exe plus ein DLLs-Verzeichnis.
  • Linux: ein App-Verzeichnis und ein .AppImage produziert via appimagetool.

Code-Signing ist auf macOS implementiert via den macos.codesignIdentity-Key in deno.json (mit Ad-hoc-Signatur-Fallback für unsignierte Builds), aber Notarisierung und Stapling via notarytool sind noch nicht verkabelt. Windows-MSI-Installer, Linux-.deb/.rpm-Installer, Clipboard und secureStorage sind in der PR-Beschreibung ebenfalls noch als TODO markiert.

OS-spezifische Limits, die man vorab kennen sollte

Die PR-Beschreibung ist ungewöhnlich explizit zu den Lücken. Sechs Limitierungen werden als "degradieren gracefully" markiert, sind es aber wert, sie zu kennen:

  • Auto-Update ist unix-only. apply_pending_update, get_dylib_path und AutoUpdateState sind #[cfg(unix)], sodass auf Windows der Staged-Update-, bsdiff- und Rollback-Pfad ein No-Op ist.
  • NAPI-Native-Addon-Support ist unix-only. promote_dylib_symbols_to_global (das Re-dlopen mit RTLD_GLOBAL, das NAPI-Symbole für Addons wie next-swc sichtbar macht) ist #[cfg(unix)]; auf Windows können Frameworks, die Native-Addons laden, diese möglicherweise nicht laden.
  • Notification-Permissions sind macOS-spezifisch. Das LAUFEY-Backend wird via disclaim_spawn gestartet (posix_spawn mit disclaimter TCC-Verantwortung), sodass es sein eigener Permission-Principal wird; ohne das schlägt UNUserNotificationCenter.requestAuthorization fehl.
  • Linux ist X11-only. Der generierte Launcher erzwingt --ozone-platform=x11 und GDK_BACKEND=x11, weil der LAUFEY-Mouse/Focus/Resize-Event-Monitor XI2 auf X11 nutzt. Auf Wayland-Sessions läuft er über XWayland; natives Wayland wird nicht unterstützt.
  • Deno.dock ist macOS-only.
  • Icon-Sets werden im --hmr-Modus nicht unterstützt (jede Plattform).

Die Motivation, mit diesen Lücken auszuliefern, ist dieselbe wie bei jeder "wir liefern den ersten Cut, dokumentieren die Limits"-Release: Der Desktop-Unterbefehl ist das erste Mal, dass Deno eine Non-Server-Runtime ausliefert, und die WEF-Integration, die Deno.BrowserWindow-API, die Framework-Auto-Erkennung, die vereinten DevTools, der Auto-Updater und das Cross-Compile auf mindestens einer Plattform (macOS) zum Laufen zu bekommen, ist die Voraussetzung für alles andere. Die Cross-Plattform-Lücken sind real, aber sie sind Lücken im ersten Cut, nicht Lücken in der Architektur.

Die drei anderen PRs vom selben Morgen

Im selben Deno-main-Branch sahen drei weitere Features zwischen 06:59 und 07:15 UTC landen, vor deno desktop um 10:41 UTC. Sie sind kleiner im Scope, aber alle primärquellenverifiziert auf derselben Release und runden die Morgengeschichte "Deno fügt einiges an Plumbing hinzu" ab.

deno link und deno unlink geben einen erstklassigen CLI-Zugriff auf das links-Array in deno.json, das der User-Facing-Weg war, ein lokales JSR-Paket statt einer Registry-Version zu nutzen, aber bis jetzt keine CLI zur Manipulation hatte. deno link <path> validiert den Pfad, hängt den relativen Pfad an links an (erstellt das Array, falls es fehlt, und bewahrt die Formatierung über die bestehende CST-Maschinerie) und führt install aus. deno unlink <path-or-name> entfernt einen Eintrag per literalem Pfad, per aufgelöstem Pfad oder per JSR-Namen des gelinkten Pakets, der aus dem deno.json des Ziels gelesen wird. Wenn kein Argument passt, exit-et unlink mit Non-Zero, sodass ein Tippfehler aus Scripts und CI erkennbar ist. Als Discoverability-Fix bail-en deno add ./local-dir und deno install ./local-dir jetzt mit einem "Did you mean deno link ./local-dir?"-Hinweis, wenn der Spec zu einem linkbaren Verzeichnis auflöst.

deno test --shard=<i>/<n> bringt CI-Sharding im Stil von Vitest / Jest / Playwright zu deno test. Die entdeckten Testdateien werden für eine stabile Reihenfolge sortiert, dann in <n> konsekutive, balancierte Gruppen aufgeteilt, und nur die Dateien für <i> werden ausgeführt. Jede Datei landet in genau einem Shard, Gruppengrößen unterscheiden sich um höchstens eins, und die Auswahl passiert vor jedem --shuffle, sodass ein gegebener Shard dieselben Dateien auf jeder Maschine ausführt, unabhängig vom Shuffle-Seed. Die PR ist explizit zum Trade-off: Der Shard wird zur Laufzeit ausgewählt, nachdem der Module-Graph der gesamten Suite bereits gebaut und type-checked wurde, sodass jede Maschine immer noch die Graph-Build- und Type-Check-Kosten für die gesamte Suite zahlt. Den Shard-Prefilter vor das Type-Checking zu verschieben, sodass jede Maschine nur ihr eigenes Subset lädt und checkt, ist ein natürlicher Follow-up.

Der fetch request_builder_hook liest die Umgebungsvariablen X_DENO_FETCH_TOKEN und CDN_LOOP einmal aus und injiziert sie, falls vorhanden, als x-deno-fetch-token- und cdn-loop-Header in jeden ausgehenden fetch() (sowohl im Main-Worker als auch in Web-Workern). Der cdn-loop-Header ermöglicht es der Upstream-Infrastruktur, Request-Loops zu erkennen. Um den Fetch-Token vertrauenswürdig zu halten, wird jeder vom Nutzer gelieferte x-deno-fetch-token-Header entfernt, bevor der Runtime-Wert angewendet wird, sodass Nutzercode ihn nicht spoofen kann. Wenn keine der beiden Env-Vars gesetzt ist, werden keine zusätzlichen Header hinzugefügt. Das ist die Runtime-Seite desselben Cloud-Deployment-Plumbings, das das Deno-Deploy-Produkt nutzt, um zu identifizieren, welches Deployment einen ausgehenden Call gemacht hat.

Was als Nächstes kommt

Das Vier-PR-Cluster ist ein starkes Signal der Richtung, in die Deno geht: ein main, der Desktop als erstklassiges Target behandelt, CI-Sharding-Parität mit Vitest / Jest / Playwright hinzufügt, den npm-link-artigen Local-Package-Workflow finalisiert und die Runtime-Level-Fetch-Header exponiert, die Cloud-Deployments brauchen. Die nächste Deno-Release (vermutlich 2.8.4, da die Deno 2.8 Release Notes am 1. Juni erschienen) ist die erste Chance, dass diese Features in einem getaggten Build landen. Die deno desktop-PR war die letzte der vier, die landete, und sie ist die mit der größten zu validierenden Oberfläche, also ist der erste getaggte Build, der alle vier ausliefert, auch der, gegen den man Feedback einreichen sollte.

Häufig gestellte Fragen

Verwandte Artikel

Weitere Berichterstattung zu ähnlichen Themen und Tags.

Astro 7.0.0-beta.4 macht Sätteri zum Standard-Markdown-Prozessor und führt erweitertes Routing, benutzerdefinierten Logger und gestreamtes Rendering als stabil
frameworks

Astro 7.0.0-beta.4 macht Sätteri zum Standard-Markdown-Prozessor und führt erweitertes Routing, benutzerdefinierten Logger und gestreamtes Rendering als stabil

Astro 7.0.0-beta.4 (15. Juni 2026) aktiviert die Rust-basierte Sätteri-Markdown-Pipeline standardmäßig, entfernt das experimentelle Flag von erweitertem Routing, benutzerdefiniertem Logger und der neuen Rendering-Engine, löscht die veralteten CLI-Befehle astro db/login/logout/link/init und übernimmt den in alpha.2 eingeführten Dev-Server-Hintergrundmodus als Standard in Agentenkontexten.
GLM-5.2 von Z.ai ist ein 1M-Token-Open-Weights-Modell für Long-Horizon-Coding-Agenten: Ein Deep Dive
tooling

GLM-5.2 von Z.ai ist ein 1M-Token-Open-Weights-Modell für Long-Horizon-Coding-Agenten: Ein Deep Dive

Am 16. Juni 2026 hat Z.ai GLM-5.2 unter MIT-Lizenz veröffentlicht, mit einem soliden 1M-Token-Kontext, einem IndexShare-Sparse-Attention-Trick, der die Per-Token-FLOPs um 2,9× reduziert, einem Anti-Hack-Modul für Coding-RL und Benchmark-Zahlen, die das Modell wenige Punkte hinter Claude Opus 4.8 auf Terminal-Bench 2.1 platzieren, vor GPT-5.5 auf drei Long-Horizon-Suites, und an der Spitze der Open-Weights-Rangliste auf jedem Coding-Benchmark, den das Unternehmen zu veröffentlichen gewählt hat. Dieser Long Read geht durch die Architektur, die IndexShare + MTP-Story, die slime-Agentic-RL-Infrastruktur, das Anti-Hack-Modul, die vollständige Benchmark-Tabelle mit allen Fußnoten und was das für den Rest des Open-Weights-Long-Context-Rennens bedeutet.
Fresh 2.3: Zero JS Standard, View Transitions und WebSocket-Support
runtimes

Fresh 2.3: Zero JS Standard, View Transitions und WebSocket-Support

Fresh 2.3 hält endlich sein Versprechen von 'standardmäßig Null JavaScript', fügt native View-Transitions-Unterstützung hinzu, bringt integrierte WebSocket-Handler, CSP-Nonce-Injection und Temporal-API-Support für Islands.

Kommentare

Anmelden Melden Sie sich an, um an der Diskussion teilzunehmen.

Noch keine Kommentare. Seien Sie der Erste, der seine Gedanken teilt.