✦Engenharia

Por que escolhemos nativo em vez de Electron (e faríamos de novo)

Todo mundo nos disse para usar Electron. Publique uma vez, rode em todo lugar. Ande rápido. Fizemos o contrário — SwiftUI na Apple, Jetpack Compose no Android, C++/WinRT no Windows, Metal e Vulkan puros onde precisávamos de pixels no tempo certo. Aqui está o que aprendemos construindo quatro clientes nativos para um único produto.

O caminho fácil vs o caminho certo

Quando você diz que está construindo um app de desktop remoto do zero em 2024, a primeira pergunta é sempre: “Por que não usar simplesmente o Electron?”

É uma pergunta justa. O Electron move alguns dos apps de maior sucesso do planeta — VS Code, Slack, Discord, o wrapper de desktop do Figma. Ele permite escrever uma vez e distribuir em todo lugar. Os seus desenvolvedores web viram desenvolvedores de desktop da noite para o dia. A vantagem no tempo de chegada ao mercado é real.

Olhamos os números, pesamos as concessões e escolhemos o caminho mais difícil possível: totalmente nativo em todas as plataformas. SwiftUI no iOS e no macOS. Jetpack Compose no Android. C++/WinRT no Windows. Metal para renderização na Apple. Vulkan em todo o resto. Um servidor Go personalizado no centro.

Não porque gostamos de sofrer, embora em alguns dias pareça. Mas porque, para este tipo de app, o nativo não é um luxo. É um requisito.

O imposto do Electron é real

Vamos começar pelo que o Electron realmente é: uma janela de navegador Chromium fingindo ser um app de desktop. Isso não é uma crítica — é arquitetura. E, para muitos aplicativos, é perfeitamente adequado.

Mas para um desktop remoto? Você está transmitindo pixels de outro computador e renderizando-os em tempo real, enquanto captura cada evento de entrada e o envia de volta. A latência não é um extra desejável. Ela é o produto inteiro.

Isto é o que medimos quando prototipamos as duas abordagens:

Os 380 MB não são o Electron sendo inchado. É o Chromium fazendo o trabalho dele — V8, um processo de GPU, processos utilitários, um mecanismo de navegador inteiro. É uma engenharia impressionante. Só que é uma engenharia projetada para outro problema.

Quadros importam mais do que recursos

O desktop remoto é uma das poucas categorias de app em que cada quadro importa. Perca um quadro e o usuário sente. Some 16 ms de latência de entrada e um designer não consegue traçar curvas suaves. Some 32 ms e um jogador não consegue jogar.

Com a renderização nativa, falamos diretamente com a GPU. Nas plataformas Apple, o VideoToolbox nos dá acesso direto à decodificação de vídeo por hardware. Pegamos um quadro H.265 da rede, decodificamos por hardware e o exibimos — sem que o quadro jamais toque a memória principal. O pipeline de decodificação até a exibição roda em menos de 4 ms em um Mac moderno.

No Electron, esse mesmo quadro passa pelo compositor do Chromium, pela ponte de IPC, é pintado pelo Skia e depois composto de novo pelo sistema. Cada salto acrescenta latência. Cada salto acrescenta jitter. E o jitter — a temporização irregular dos quadros — é o que faz o desktop remoto parecer estranho, mesmo quando a média de FPS parece boa.

Não escolhemos o nativo por purismo. Escolhemos porque a física do nosso problema exigiu — cerca de 8 ms de processamento na rede local (o restante é o ritmo de atualização de 60 Hz da sua própria tela) não deixam espaço para um navegador no meio.

Quadro de capacidades: nativo vs web

O debate Electron vs nativo costuma ficar preso no achismo. Então anotamos as sete capacidades do sistema de que o Remio depende a cada segundo de cada sessão e perguntamos, sem rodeios: como cada uma se sai em cada ambiente de execução?

CapacidadeNativoWeb / Electron
Decodificação por hardware a 60 fps● VideoToolbox / D3D11VA direto○ Via WebCodecs, com jitter
Áudio USB de baixa latência● CoreAudio / WASAPI— Em sandbox, 40 ms+
Monitoramento de entrada do teclado● CGEvent / SendInput— Bloqueado fora do foco
Acesso à GPU por Metal / D3D11● Texturas sem cópia○ WebGPU, saltos de cópia
Sistema de arquivos local● Completo, delimitado pelo sistema○ Só por seletor, com avisos
Várias janelas, várias telas● Janelas nativas do sistema○ Adaptações de BrowserWindow
Persistência em segundo plano● LaunchAgent / serviço— Suspenso ao ocultar

Cada linha é um recurso que entregamos hoje. Cada — na coluna web é uma solução alternativa que teríamos de inventar, documentar e pedir desculpas por ela. Ir nativo significa tratar essas capacidades como primitivas, e não como polyfills.

Cidadania de plataforma

Aqui está algo de que a turma do escreva-uma-vez-rode-em-qualquer-lugar raramente fala: os usuários percebem.

Eles percebem quando um app não respeita as transições do modo escuro do sistema. Quando a física da rolagem parece um pouco errada. Quando o app não aparece no Spotlight ou não lida direito com o gerenciamento de janelas do macOS. Quando o menu de contexto parece uma página web em vez de um menu nativo.

Isso não são extras desejáveis. É a diferença entre um app que as pessoas toleram e um app que as pessoas amam. No iOS isso é especialmente crítico — a revisão da App Store rejeita apps que parecem não nativos, e com razão.

Com o SwiftUI, ganhamos tudo isso de graça. Dynamic Type, acessibilidade com VoiceOver, hápticos do sistema, multitarefa no iPad, atalhos de teclado no Mac. Não reimplementamos recursos da plataforma. Nós os usamos.

O custo também é real

Vamos ser honestos sobre a desvantagem: ir nativo é caro. Não em dólares — em tempo e complexidade.

Mantemos quatro bases de código de interface. A nossa camada de rede e de codecs é compartilhada (Go para a sinalização, C++ para o protocolo de streaming), mas cada pixel que você vê na tela é código específico da plataforma. Um recurso que leva um dia no Electron leva de três a cinco dias para nós, porque o construímos quatro vezes, ajustado para cada plataforma.

Já tivemos semanas em que uma única animação funcionava lindamente no iOS, estava quebrada no Android e travando no Windows. A matriz de depuração é brutal.

Mas aprendemos isto: o caminho mais difícil e o caminho certo costumam ser o mesmo caminho. Os nossos usuários não conhecem nem se importam com a nossa arquitetura. Eles sabem que o Remio parece rápido, parece certo e não devora a bateria no café da manhã.

Faríamos de novo

Sem hesitar.

A abordagem nativa nos deu um desempenho que o Electron, fundamentalmente, não consegue igualar para esse caso de uso. Nos deu apps que parecem pertencer a cada plataforma. Nos deu uma pegada de memória abaixo de 45 MB em vez de 380 MB. Nos deu cerca de 8 ms de processamento na rede local (o restante é o ritmo de atualização de 60 Hz da sua própria tela), onde um concorrente embrulhado em navegador fica acima de 60 ms.

E, principalmente, nos deu uma barreira técnica. Construir nativo em quatro plataformas é difícil o bastante para que a maioria dos concorrentes não o faça. Essa dificuldade é a nossa vantagem.

A categoria de desktop remoto foi dominada por apps web embrulhados em Electron e por apps nativos legados que não são atualizados de forma significativa há anos. Há espaço para algo que seja ao mesmo tempo moderno e nativo — algo construído do zero pensando no hardware de hoje.

Esse é o Remio. Construído do jeito difícil, porque algumas coisas valem a pena ser feitas direito.

Ícone do app Remio

Sinta a diferença que o nativo faz

O Remio é grátis, nativo em todas as plataformas e criptografado de ponta a ponta. Pegada abaixo de 45 MB, cerca de 8 ms de processamento na rede local (o restante é o ritmo de atualização de 60 Hz da sua própria tela) — construído do jeito difícil para parecer certo.

Grátis100% nativoCriptografia de ponta a ponta