12k
All articles

Creación de aplicaciones de escritorio con deno desktop

Deno desktop compila apps TypeScript en binarios nativos, con webview o CEF, soporte de frameworks, compilación cruzada y límites.

OpenReplay Team
OpenReplay Team
Creación de aplicaciones de escritorio con deno desktop

deno desktop compila un proyecto de Deno en una aplicación de escritorio autónoma: tu código, el runtime de Deno y un motor de renderizado en un único binario por plataforma. Se lanzó con Deno 2.9. Lo que lo distingue de Electron y Tauri es que el motor de renderizado es una decisión que se toma en tiempo de compilación. Puedes elegir el WebView del sistema operativo o un Chromium empaquetado, y ninguno de Electron, Electrobun, Tauri o Dioxus ofrece esa alternativa.

Cualquiera que haya publicado una aplicación con Electron conoce la conversación del instalador de 100 MB, y cualquiera que haya publicado una aplicación con Tauri conoce ese bug que solo se reproduce en WebKitGTK. Esos dos frameworks se sitúan en extremos opuestos de un mismo eje, y hasta ahora elegir un framework significaba elegir un motor de renderizado para siempre.

Este es un primer vistazo a la tercera opción, dirigido a lectores que ya conocen el compromiso entre Electron y Tauri. Cubre qué produce el comando, el programa más pequeño que ilustra el modelo, cuánto cuesta cada backend en megabytes, qué proyectos de framework acepta sin modificaciones, cómo funciona la compilación cruzada y qué sigue faltando. La discusión entre Electron y Tauri en sí se aborda en una comparación entre Electron y Tauri aparte.

Puntos clave

  • deno desktop se lanzó en la versión estable Deno 2.9.0 el 25 de junio de 2026, y la publicación del lanzamiento todavía lo etiqueta como experimental, con algunas funciones específicas de plataforma aún pendientes.
  • El backend predeterminado webview renderiza a través de WebView2 en Windows, WKWebView en macOS y WebKitGTK en Linux; el backend opcional cef empaqueta Chromium para obtener un renderizado idéntico en todas las plataformas.
  • La página de comparación de Deno sitúa una aplicación basada en WebView en aproximadamente 40 MB y una basada en CEF en aproximadamente 150 MB, frente a más de ~100 MB para Electron y ~2–10 MB para Tauri.
  • Un handler de Deno.serve() dentro de un entrypoint de escritorio no recibe puerto ni hostname; el runtime lo vincula a la dirección que carga la ventana.
  • --target y --all-targets permiten compilación cruzada a cinco triples de plataforma desde cualquier host sin necesidad de un toolchain de Rust, con el .dmg de macOS como la única excepción atada al host.

¿Qué es deno desktop?

Apunta deno desktop a un entrypoint de Deno o a un proyecto de framework web, y lo que obtienes es una aplicación de escritorio que dibuja su interfaz en un webview y ejecuta su lógica en Deno. La publicación del lanzamiento de 2.9 lo presenta como la característica principal y, en esa misma sección, lo marca como experimental, con la superficie de la API todavía estabilizándose. Llegó en la versión estable 2.9.0, no en una canary, tal como registran las notas de la versión v2.9.0 bajo feat: deno desktop subcommand.

Tres cosas entran en el binario de cada plataforma: tu código, el runtime de Deno y un backend de renderizado. La comunicación entre el lado de Deno y el webview ocurre a través de canales in-process en lugar de IPC basado en sockets, lo cual es un modelo distinto al paso de mensajes entre proceso principal y renderer de Electron. Las superficies nativas como Deno.BrowserWindow y Deno.Tray están integradas en el runtime, de modo que el control de ventanas y los iconos de la bandeja del sistema no requieren ningún paquete de terceros.

El programa deno desktop más pequeño

La aplicación de escritorio mínima es un único handler de Deno.serve() que devuelve HTML, más un comando.

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

Fíjate en el argumento ausente. En un servidor Deno normal pasarías un puerto; aquí lo omites, porque en un entrypoint de escritorio el runtime entrega al handler la dirección a la que la ventana ya está apuntando. La aplicación compilada abre una ventana nativa sobre ese servidor local. Esta es la parte menos evidente del modelo de programación: el servidor HTTP es el transporte de la UI, y el runtime conecta ambos extremos por ti.

¿Deberías usar el backend webview o cef?

El motor de renderizado es una decisión de tiempo de compilación, y es la razón por la que deno desktop ocupa un espacio que ningún competidor llena. Electron empaqueta únicamente Chromium y Tauri usa únicamente el WebView del sistema. deno desktop hace cualquiera de las dos cosas, seleccionable con --backend o con el campo desktop.backend en deno.json.

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

La página de backends nombra los motores detrás de la opción predeterminada: WKWebView en macOS, WebView2 en Windows, WebKitGTK en Linux. También documenta dos limitaciones de ese backend que importan a quien lo esté evaluando: las DevTools son exclusivas de CEF, y WebGPU en Linux requiere CEF. El backend cef coloca una copia del Chromium Embedded Framework dentro del bundle de la aplicación, que esa misma página dimensiona en ~150 MB solo para el framework.

La página de comparación de Deno enumera los tamaños de aplicación resultantes como aproximaciones:

HerramientaMotorTamaño de la app (cifra de Deno)
deno desktop, webviewWebView del SO~40 MB
deno desktop, cefChromium empaquetado~150 MB
ElectronChromium empaquetado~100 MB+
TauriWebView del SO~2–10 MB

La página de distribución aporta otro dato: un hello-world sobre el backend WebView pesa unos 66 MB, y --compress lo reduce a 19 MB. Considera todas estas cifras como propias de Deno, no como mediciones de tu aplicación.

La regla de una línea de la publicación del lanzamiento es quedarte con webview a menos que necesites un motor idéntico en todas partes. Ampliando eso con las limitaciones documentadas se obtiene una decisión práctica: usa webview por defecto; cambia a cef cuando tu UI dependa de un renderizado específico de Chromium, cuando no puedas probar en los tres motores de SO, cuando necesites DevTools durante el desarrollo o cuando necesites WebGPU en Linux. El precio del cambio es la diferencia entre las dos filas de arriba.

¿Qué frameworks detecta deno desktop?

Apuntado a un proyecto de framework existente, deno desktop . determina de qué framework se trata a partir del archivo de configuración o de package.json, incrusta la salida del build y ejecuta el servidor de producción del framework como handler de Deno.serve(). Para Next.js, Astro, Fresh y Nuxt, las notas por framework no muestran nada más que el propio comando de build del framework seguido de deno desktop ., sin adaptador ni configuración adicional. SvelteKit también se detecta, pero solo a través de la salida del adaptador de Deno Deploy o del adaptador de Node; React Router necesita un app/entry.server.tsx compatible con Deno.

Ejecuta primero el build del framework. El comando empaqueta lo que ese build produjo; no va a disparar next build ni astro build por ti.

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

Con --hmr, la ventana de la aplicación apunta directamente al servidor de desarrollo del propio framework, de modo que desarrollar se siente muy parecido a trabajar en una pestaña del navegador: el estado sobrevive a una edición, el fast refresh funciona y los errores llegan a través del overlay habitual.

¿Cómo se hace compilación cruzada de aplicaciones deno desktop?

--target <triple> compila para otra plataforma y --all-targets compila para todas las soportadas, desde cualquier host, sin toolchain de Rust. La página de distribución lista cinco targets: aarch64-apple-darwin, x86_64-apple-darwin, x86_64-pc-windows-msvc, aarch64-unknown-linux-gnu y x86_64-unknown-linux-gnu.

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

El mecanismo es descarga, no compilación. Para el target solicitado, la CLI descarga un denort precompilado y un archivo de backend precompilado, verificando ambos contra sus hashes SHA-256 antes de usarlos. Por eso funciona donde Tauri y Dioxus no. Sus toolchains de Rust deben compilar en la plataforma de destino, así que cada SO necesita su propia máquina de build. Electron sí puede hacer compilación cruzada mediante electron-builder, de modo que el contraste es específicamente con las herramientas basadas en Rust. La única excepción del lado de Deno es el .dmg de macOS, que delega en hdiutil y debe generarse en un Mac.

Madurez, con honestidad

Electron ejecuta Slack, Visual Studio Code y Notion; Tauri 2 lleva años de lanzamientos y targets móviles a sus espaldas; deno desktop llegó con 2.9.0, y cada release de parche 2.9 posterior ha traído correcciones para desktop, incluida la 2.9.6. La documentación es franca sobre lo que todavía no está.

Los formatos de salida están más avanzados de lo que sugiere la lista de carencias de la página de comparación. La página de distribución documenta .app y .dmg en macOS, un directorio de aplicación o .msi en Windows, y un directorio de aplicación, .AppImage, .deb o .rpm en Linux, elegidos según la extensión de --output. Los instaladores .msi, .deb y .rpm se incluyeron ya en la propia 2.9.0, según las notas del lanzamiento.

Las carencias confirmadas:

  • Auto-actualización en Windows. Solo macOS y Linux completan realmente la actualización: aplican el parche preparado y, si la nueva versión no arranca, revierten a la anterior. Windows descarga y prepara un parche pero nunca lo instala, así que nada cambia en el siguiente arranque. La página de auto-actualización indica tratar la auto-actualización en Windows como no soportada por ahora.
  • Notarización. La firma se ejecuta automáticamente en un host macOS, pero la sección de firma de código señala que todavía tienes que notarizar a mano, con xcrun notarytool submit como paso aparte.
  • Móvil. No hay targets de iOS ni Android, donde Tauri 2 tiene ambos.
  • Almacenamiento seguro, prompts de permisos en tiempo de ejecución, runtime CEF compartido. La página de comparación lista los tres como ausentes o en el roadmap; el runtime compartido es el elemento que reduciría el tamaño de las aplicaciones con CEF, y es una promesa, no un lanzamiento.

¿Quién debería probar deno desktop ahora?

Pruébalo ahora si ya usas Deno, tu equipo escribe TypeScript y no Rust, y la aplicación es una herramienta interna o un envoltorio de escritorio sobre una base de código existente en Next.js, Astro, Fresh o Nuxt, donde un build WebView de 40 MB es aceptable y una audiencia de macOS o Linux cubre la auto-actualización. Espera si distribuyes a usuarios de Windows que necesitan actualizaciones in situ, si necesitas móvil desde la misma base de código, o si necesitas un pipeline de distribución con años de herramientas de firma e instaladores detrás. La etiqueta de experimental en la publicación del lanzamiento es precisa: el modelo es sólido y los comandos funcionan como está documentado, pero la superficie aún puede moverse entre releases de parche.

Conclusión

deno desktop es una tercera opción real porque separa la decisión del motor de renderizado de la decisión del framework, y cobra un precio documentado por cada lado de esa elección. La forma más barata de evaluarlo es ejecutar deno desktop . dentro de un proyecto de framework que ya tengas, una vez con el backend predeterminado y otra con --backend cef, y comparar ambos artefactos frente a las carencias enumeradas arriba.

Preguntas frecuentes

¿Cómo llama el webview al código de Deno en una aplicación deno desktop?

Mediante bindings. Del lado de Deno adjuntas un handler a una ventana con win.bind(name, handler); el JavaScript de la página llama entonces a bindings.name(args) y recibe de vuelta una promesa con lo que sea que el handler haya devuelto. Cada ventana mantiene su propio conjunto de bindings, de modo que un handler registrado en un Deno.BrowserWindow es invisible para otro. La llamada viaja por canales in-process en lugar de IPC por sockets, y cuando un handler lanza una excepción, lo que llega al webview es un objeto plano con name, message y stack en lugar de un Error real.

¿Qué es el backend raw en deno desktop y cuándo deberías usarlo?

Ejecuta una aplicación de escritorio sin ningún motor web. Conservas ventanas, eventos de entrada y la superficie de la API nativa, pero no hay nada donde renderizar HTML: sin webview, sin vinculación automática de Deno.serve() y sin proxy de bindings. Es adecuado para aplicaciones que dibujan su propia interfaz con WebGPU, Skia o código de dibujo personalizado. La única forma de seleccionarlo es el campo desktop.backend en deno.json, ya que el flag --backend solo acepta cef y webview.

¿Puedo cambiar una aplicación deno desktop entre los backends webview y cef sin modificar el código?

Sí. La página de backends de Deno trata CEF y WebView como intercambiables: ventanas, bindings, eventos, navegación y ejecución de JS se comportan igual en cualquiera de los dos, y solo el backend raw rompe esa portabilidad. Compilar para un backend o un target que no hayas usado antes descarga primero un archivo precompilado, unos cientos de megabytes en el caso de CEF, verificado por checksum y conservado en el directorio de caché de Deno para que los builds posteriores se salten la descarga.

¿Se aplican los permisos de Deno dentro de una aplicación deno desktop?

Sí, pero provienen de los permisos compilados en el binario y no de prompts. Un binding se ejecuta dentro del runtime de Deno con lo que se le haya concedido al proceso, así que un handler que lee un archivo necesita acceso de lectura concedido al arranque, y nada de lo que haga el webview puede ampliarlo. La documentación es clara en que no se dispara ningún prompt de permisos por separado en tiempo de ejecución, así que trata cualquier dato que un binding acepte desde la página como entrada no confiable y valídalo.

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.