12k
All articles

Criando Aplicações Desktop com deno desktop

Deno desktop compila apps TypeScript em binários nativos, com webview ou CEF, suporte a frameworks, compilação cruzada e limites.

OpenReplay Team
OpenReplay Team
Criando Aplicações Desktop com deno desktop

O deno desktop compila um projeto Deno em uma aplicação desktop autocontida: seu código, o runtime do Deno e um motor de renderização em um único binário por plataforma. Ele foi lançado com o Deno 2.9. O que o diferencia do Electron e do Tauri é que o motor de renderização é uma escolha feita em tempo de build. Você opta pelo WebView do sistema operacional ou por um Chromium empacotado, e nenhum dos concorrentes — Electron, Electrobun, Tauri ou Dioxus — oferece essa alternância.

Quem já publicou uma aplicação Electron conhece bem a discussão sobre o instalador de 100 MB, e quem já publicou uma aplicação Tauri conhece aquele bug que só se reproduz no WebKitGTK. Esses dois frameworks ficam em extremos opostos de um mesmo eixo e, até agora, escolher um framework significava escolher um motor de renderização em definitivo.

Este é um primeiro olhar sobre a terceira opção, voltado a leitores que já conhecem o trade-off entre Electron e Tauri. O texto aborda o que o comando produz, o menor programa que demonstra o modelo, quanto cada backend custa em megabytes, quais projetos de framework ele aceita sem modificações, como funciona a compilação cruzada e o que ainda está faltando. A discussão entre Electron e Tauri em si é tratada em uma comparação separada entre Electron e Tauri.

Principais Pontos

  • O deno desktop foi lançado na versão estável Deno 2.9.0 em 25 de junho de 2026, e o post de lançamento ainda o rotula como experimental, com alguns recursos de plataforma ainda não disponíveis.
  • O backend padrão webview renderiza através do WebView2 no Windows, WKWebView no macOS e WebKitGTK no Linux; o backend opcional cef empacota o Chromium para obter renderização idêntica em todas as plataformas.
  • A página de comparação do Deno estima uma aplicação com WebView em aproximadamente 40 MB e uma aplicação com CEF em aproximadamente 150 MB, contra mais de ~100 MB do Electron e ~2–10 MB do Tauri.
  • Um handler Deno.serve() dentro de um entrypoint desktop não recebe porta nem hostname; o runtime o vincula ao endereço que a janela carrega.
  • --target e --all-targets fazem compilação cruzada para cinco triplas de plataforma a partir de qualquer host, sem necessidade de toolchain Rust, com o .dmg do macOS sendo a única exceção dependente do host.

O Que É o deno desktop?

Aponte o deno desktop para um entrypoint Deno ou para um projeto de framework web, e o que você recebe de volta é uma aplicação desktop que desenha sua interface em um webview e executa sua lógica no Deno. O post de lançamento do 2.9 o apresenta como o recurso principal e, na mesma seção, o marca como experimental, com a superfície da API ainda em estabilização. Ele chegou na versão estável 2.9.0, e não em uma canary, conforme registram as notas de lançamento da v2.9.0 sob feat: deno desktop subcommand.

Três elementos entram no binário de cada plataforma: seu código, o runtime do Deno e um backend de renderização. A comunicação entre o lado Deno e o webview acontece por canais in-process em vez de IPC baseado em sockets, o que representa um modelo diferente da troca de mensagens entre main e renderer do Electron. Superfícies nativas como Deno.BrowserWindow e Deno.Tray estão embutidas no runtime, então o controle de janelas e os ícones da bandeja do sistema não exigem nenhum pacote de terceiros.

O Menor Programa deno desktop

A aplicação desktop mínima é um único handler Deno.serve() que retorna HTML, mais um comando.

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

Repare no argumento ausente. Em um servidor Deno comum você passaria uma porta; aqui você a omite, porque em um entrypoint desktop o runtime entrega ao handler o endereço para o qual a janela já está apontada. A aplicação compilada abre uma janela nativa nesse servidor local. Essa é a parte menos óbvia do modelo de programação: o servidor HTTP é o transporte da UI, e o runtime conecta as duas pontas para você.

Você Deve Usar o Backend webview ou cef?

O motor de renderização é uma decisão de tempo de build, e é a razão pela qual o deno desktop ocupa um espaço que nenhum concorrente preenche. O Electron empacota apenas o Chromium e o Tauri usa apenas o WebView do sistema. O deno desktop faz qualquer um dos dois, selecionado com --backend ou com o campo desktop.backend no deno.json.

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

A página de backends nomeia os motores por trás do padrão: WKWebView no macOS, WebView2 no Windows, WebKitGTK no Linux. Ela também documenta dois limites desse backend que importam para quem está avaliando a ferramenta: o DevTools é exclusivo do CEF, e a WebGPU no Linux exige o CEF. O backend cef coloca uma cópia do Chromium Embedded Framework dentro do bundle da aplicação, cujo tamanho a mesma página estima em ~150 MB apenas para o framework.

A página de comparação do Deno lista os tamanhos resultantes das aplicações como aproximações:

FerramentaMotorTamanho da aplicação (estimativa do Deno)
deno desktop, webviewWebView do SO~40 MB
deno desktop, cefChromium empacotado~150 MB
ElectronChromium empacotado~100 MB+
TauriWebView do SO~2–10 MB

A página de distribuição traz outro dado: um hello-world no backend WebView pesa cerca de 66 MB, e --compress reduz isso para 19 MB. Encare todos esses valores como números do próprio Deno, e não como medições da sua aplicação.

A regra de uma linha do post de lançamento é permanecer no webview a menos que você precise de um motor idêntico em todos os lugares. Estendendo isso com os limites documentados, chega-se a uma decisão prática: use webview por padrão; mude para cef quando sua UI depender de renderização específica do Chromium, quando você não puder testar nos três motores de SO, quando precisar do DevTools durante o desenvolvimento ou quando precisar de WebGPU no Linux. O preço da troca é a diferença entre as duas linhas acima.

Quais Frameworks o deno desktop Detecta?

Apontado para um projeto de framework existente, o deno desktop . identifica qual é o framework a partir do arquivo de configuração ou do package.json, embute o resultado do build e executa o servidor de produção do framework como o handler Deno.serve(). Para Next.js, Astro, Fresh e Nuxt, as notas por framework não mostram nada além do próprio comando de build do framework seguido de deno desktop ., sem adaptador e sem configuração extra. O SvelteKit também é detectado, mas apenas através da saída do adaptador do Deno Deploy ou do adaptador Node; o React Router precisa de um app/entry.server.tsx compatível com Deno.

Execute o build do framework primeiro. O comando empacota o que esse build produziu; ele não vai disparar next build ou astro build em seu nome.

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

Com --hmr, a janela da aplicação aponta diretamente para o servidor de desenvolvimento do próprio framework, de modo que o desenvolvimento se parece bastante com trabalhar em uma aba do navegador: o estado sobrevive a uma edição, o fast refresh funciona e os erros chegam pelo overlay habitual.

Como Fazer Compilação Cruzada de Aplicações deno desktop?

--target <triple> compila para uma outra plataforma e --all-targets compila para todas as suportadas, a partir de qualquer host, sem toolchain Rust. A página de distribuição lista cinco alvos: aarch64-apple-darwin, x86_64-apple-darwin, x86_64-pc-windows-msvc, aarch64-unknown-linux-gnu e x86_64-unknown-linux-gnu.

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

O mecanismo é download, não compilação. Para o alvo solicitado, a CLI baixa um denort pré-compilado e um arquivo de backend pré-compilado, verificando ambos contra seus hashes SHA-256 antes do uso. É por isso que funciona onde Tauri e Dioxus não funcionam. Suas toolchains Rust precisam compilar na plataforma-alvo, então cada SO exige sua própria máquina de build. O Electron consegue fazer cross-build através do electron-builder, então o contraste é especificamente com as ferramentas baseadas em Rust. A única exceção do lado do Deno é o .dmg do macOS, que recorre ao hdiutil e precisa ser produzido em um Mac.

Maturidade, Sinceramente

O Electron roda o Slack, o Visual Studio Code e o Notion; o Tauri 2 tem anos de releases e alvos mobile em seu histórico; o deno desktop chegou com o 2.9.0, e cada patch release do 2.9 desde então trouxe correções relacionadas ao desktop, incluindo o 2.9.6. A documentação é franca sobre o que ainda não existe.

Os formatos de saída estão mais avançados do que a lista de lacunas da página de comparação sugere. A página de distribuição documenta .app e .dmg no macOS, um diretório de aplicação ou .msi no Windows, e um diretório de aplicação, .AppImage, .deb ou .rpm no Linux, escolhidos pela extensão do --output. Os instaladores .msi, .deb e .rpm chegaram já no próprio 2.9.0, conforme as notas de lançamento.

As lacunas confirmadas:

  • Auto-update no Windows. Apenas macOS e Linux concluem de fato a atualização: eles aplicam o patch preparado e, se a nova versão falhar ao iniciar, revertem para a antiga. O Windows baixa e prepara um patch, mas nunca o aplica, então nada muda na próxima inicialização. A página de auto-update recomenda tratar o auto-update no Windows como não suportado por enquanto.
  • Notarização. A assinatura acontece automaticamente em um host macOS, mas a seção de code signing destaca que você ainda precisa notarizar manualmente, com xcrun notarytool submit como uma etapa à parte.
  • Mobile. Não há alvos iOS ou Android, enquanto o Tauri 2 tem ambos.
  • Armazenamento seguro, prompts de permissão em runtime, runtime CEF compartilhado. A página de comparação lista os três como ausentes ou no roadmap; o runtime compartilhado é o item que reduziria o tamanho das aplicações CEF, e ele é uma promessa, não um lançamento.

Quem Deve Experimentar o deno desktop Agora?

Experimente agora se você já usa Deno, se sua equipe escreve TypeScript e não Rust, e se a aplicação é uma ferramenta interna ou um wrapper desktop em torno de uma base de código existente em Next.js, Astro, Fresh ou Nuxt, onde um build WebView de 40 MB é aceitável e um público macOS ou Linux cobre o auto-update. Espere se você distribui para usuários Windows que precisam de atualizações in-place, se precisa de mobile a partir da mesma base de código, ou se precisa de um pipeline de distribuição com anos de ferramental de assinatura e instaladores por trás. O rótulo experimental no post de lançamento é preciso: o modelo é sólido e os comandos funcionam conforme documentado, mas a superfície ainda pode mudar entre patch releases.

Conclusão

O deno desktop é uma terceira opção de verdade porque separa a decisão sobre o motor de renderização da decisão sobre o framework, e cobra um preço documentado por cada lado dessa escolha. A forma mais barata de avaliá-lo é rodar deno desktop . dentro de um projeto de framework que você já tenha, uma vez com o backend padrão e outra com --backend cef, e comparar os dois artefatos contra as lacunas listadas acima.

Perguntas Frequentes

Como o webview chama código Deno em uma aplicação deno desktop?

Através de bindings. No lado Deno você associa um handler a uma janela com win.bind(name, handler); o JavaScript da página então chama bindings.name(args) e recebe de volta uma promise carregando o que quer que o handler tenha retornado. Cada janela mantém seu próprio conjunto de bindings, então um handler registrado em um Deno.BrowserWindow é invisível para outro. A chamada trafega por canais in-process em vez de IPC por sockets e, quando um handler lança uma exceção, o que chega ao webview é um objeto simples contendo name, message e stack, e não um Error de verdade.

O que é o backend raw no deno desktop e quando você deve usá-lo?

Ele executa uma aplicação desktop sem nenhum motor web. Você mantém janelas, eventos de entrada e a superfície de API nativa, mas não há nada onde renderizar HTML: sem webview, sem vinculação automática de Deno.serve() e sem proxy de bindings. Ele atende aplicações que desenham a própria interface com WebGPU, Skia ou código de desenho customizado. A única forma de selecioná-lo é pelo campo desktop.backend no deno.json, já que a flag --backend aceita apenas cef e webview.

Posso alternar uma aplicação deno desktop entre os backends webview e cef sem mudar o código?

Sim. A página de backends do Deno trata CEF e WebView como intercambiáveis: janelas, bindings, eventos, navegação e execução de JS se comportam da mesma forma em ambos, e apenas o backend raw quebra essa portabilidade. Compilar para um backend ou alvo que você ainda não usou baixa primeiro um arquivo pré-compilado, com algumas centenas de megabytes no caso do CEF, verificado por checksum e mantido no diretório de cache do Deno, de modo que builds posteriores dispensam o download.

As permissões do Deno se aplicam dentro de uma aplicação deno desktop?

Sim, mas elas vêm das permissões compiladas no binário, e não de prompts. Um binding é executado dentro do runtime do Deno com aquilo que foi concedido ao processo, então um handler que lê um arquivo precisa de acesso de leitura concedido na inicialização, e nada que o webview faça pode ampliar isso. A documentação é clara ao dizer que nenhum prompt de permissão separado é disparado em runtime, então trate qualquer coisa que um binding aceite da página como entrada não confiável e valide-a.

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.