✦Ingeniería

Por qué elegimos lo nativo en lugar de Electron (y lo volveríamos a hacer)

Todos nos dijeron que usáramos Electron. Lanzar una vez, correr en todas partes. Moverse rápido. Hicimos lo contrario: SwiftUI en Apple, Jetpack Compose en Android, C++/WinRT en Windows, Metal y Vulkan puros donde necesitábamos píxeles a tiempo. Esto es lo que aprendimos al construir cuatro clientes nativos para un solo producto.

El camino fácil frente al camino correcto

Cuando le cuentas a la gente que estás construyendo una app de escritorio remoto desde cero en 2024, la primera pregunta siempre es: «¿Por qué no usar Electron?»

Es una pregunta justa. Electron impulsa algunas de las apps más exitosas del planeta: VS Code, Slack, Discord, el envoltorio de escritorio de Figma. Te permite escribir una vez y desplegar en todas partes. Tus desarrolladores web se vuelven desarrolladores de escritorio de la noche a la mañana. La ventaja de salir rápido al mercado es real.

Miramos los números, sopesamos las concesiones y elegimos el camino más difícil posible: totalmente nativo en cada plataforma. SwiftUI en iOS y macOS. Jetpack Compose en Android. C++/WinRT en Windows. Metal para renderizar en Apple. Vulkan en todo lo demás. Un servidor Go a medida en el centro.

No porque disfrutemos sufrir, aunque algunos días lo parezca. Sino porque, para este tipo de app, lo nativo no es un lujo. Es un requisito.

El impuesto de Electron es real

Empecemos por lo que Electron es en realidad: una ventana de navegador Chromium que finge ser una app de escritorio. No es una crítica, es arquitectura. Y para muchas aplicaciones está perfectamente bien.

¿Pero para un escritorio remoto? Estás transmitiendo píxeles desde otra computadora y renderizándolos en tiempo real mientras capturas cada evento de entrada y lo envías de vuelta. La latencia no es un extra. Es todo el producto.

Esto es lo que medimos cuando hicimos prototipos de ambos enfoques:

Los 380 MB no son Electron siendo inflado. Es Chromium haciendo su trabajo: V8, un proceso de GPU, procesos de utilidad, todo un motor de navegador. Es ingeniería impresionante. Solo que ingeniería diseñada para un problema distinto.

Los fotogramas importan más que las funciones

El escritorio remoto es una de las pocas categorías de apps donde cada fotograma importa. Pierde un fotograma y el usuario lo siente. Agrega 16 ms de latencia de entrada y un diseñador no puede dibujar curvas suaves. Agrega 32 ms y un jugador no puede jugar.

Con el renderizado nativo hablamos directamente con la GPU. En las plataformas de Apple, VideoToolbox nos da acceso directo a la decodificación de video por hardware. Tomamos un fotograma H.265 de la red, lo decodificamos por hardware y lo mostramos, sin que el fotograma toque nunca la memoria principal. El proceso de decodificar a mostrar corre en menos de 4 ms en una Mac moderna.

En Electron, ese mismo fotograma viaja por el compositor de Chromium, por el puente IPC, lo pinta Skia y luego el sistema operativo lo compone otra vez. Cada salto suma latencia. Cada salto suma jitter. Y el jitter, la temporización inconsistente de los fotogramas, es lo que hace que el escritorio remoto se sienta raro aunque los FPS promedio se vean bien.

No elegimos lo nativo por purismo. Lo elegimos porque la física de nuestro problema lo exigía: unos 8 ms de procesamiento en LAN (el resto es la cadencia de actualización de 60 Hz de tu propia pantalla) no dejan espacio para un navegador en medio.

Libro de capacidades: nativo vs web

El debate Electron contra nativo suele quedarse en las sensaciones. Así que anotamos las siete capacidades del sistema operativo de las que Remio depende cada segundo de cada sesión y preguntamos sin rodeos: ¿cómo le va a cada una con cada entorno de ejecución?

CapacidadNativoWeb / Electron
Decodificación por hardware a 60 fps● VideoToolbox / D3D11VA directo○ Con WebCodecs, jitter
Audio USB de baja latencia● CoreAudio / WASAPI— En sandbox, 40 ms o más
Monitoreo de la entrada del teclado● CGEvent / SendInput— Bloqueado fuera del foco
Acceso a la GPU con Metal / D3D11● Texturas sin copia○ WebGPU, saltos de copia
Sistema de archivos local● Completo, con alcance por el SO○ Solo selector, con avisos
Varias ventanas y pantallas● Ventanas nativas del SO○ Parches de BrowserWindow
Persistencia en segundo plano● LaunchAgent / servicio— Suspendido al ocultarse

Cada fila es una función que lanzamos hoy. Cada «—» de la columna web es un truco que tendríamos que inventar, documentar y por el que tendríamos que disculparnos. Ir nativos significa tratar esas capacidades como primitivas y no como parches.

Buena ciudadanía de plataforma

Hay algo de lo que rara vez habla la gente del «escribe una vez, corre donde sea»: los usuarios lo notan.

Lo notan cuando una app no respeta las transiciones del modo oscuro del sistema. Cuando la física del desplazamiento se siente un poco mal. Cuando la app no aparece en Spotlight o no maneja bien la administración de ventanas de macOS. Cuando el menú contextual parece una página web y no un menú nativo.

Esos no son extras. Son la diferencia entre una app que la gente tolera y una que la gente ama. En iOS esto es especialmente crítico: la revisión de la App Store rechaza apps que no se sienten nativas, y con razón.

Con SwiftUI, todo esto viene gratis. Dynamic Type, accesibilidad con VoiceOver, hápticos del sistema, multitarea en iPad, atajos de teclado en Mac. No reimplementamos funciones de la plataforma. Las usamos.

El costo también es real

Seamos honestos sobre la desventaja: ir nativo es caro. No en dinero, sino en tiempo y complejidad.

Mantenemos cuatro bases de código de interfaz. Nuestra capa de red y de códecs es compartida (Go para la señalización, C++ para el protocolo de transmisión), pero cada píxel que ves en pantalla es código específico de cada plataforma. Una función que toma un día en Electron nos toma de tres a cinco días, porque la construimos cuatro veces, afinada para cada plataforma.

Hemos tenido semanas en que una sola animación funcionaba de maravilla en iOS, estaba rota en Android y se veía entrecortada en Windows. La matriz de depuración es brutal.

Pero esto es lo que hemos aprendido: el camino más difícil y el camino correcto suelen ser el mismo. Nuestros usuarios no conocen ni les importa nuestra arquitectura. Saben que Remio se siente rápido, se siente bien y no se come su batería de desayuno.

¿Lo volveríamos a hacer?

Sin dudarlo.

El enfoque nativo nos dio un rendimiento que Electron, en esencia, no puede igualar para este caso de uso. Nos dio apps que se sienten propias de cada plataforma. Nos dio una huella de memoria de menos de 45 MB en lugar de 380 MB. Nos dio unos 8 ms de procesamiento en LAN (el resto es la cadencia de actualización de 60 Hz de tu propia pantalla), mientras que un competidor envuelto en navegador anda por encima de los 60 ms.

Y lo más importante: nos dio un foso técnico. Construir de forma nativa en cuatro plataformas es lo bastante difícil como para que la mayoría de los competidores no lo haga. Esa dificultad es nuestra ventaja.

La categoría del escritorio remoto ha estado dominada por apps web envueltas en Electron y apps nativas heredadas que no se han actualizado de forma significativa en años. Hay espacio para algo que sea a la vez moderno y nativo, algo construido desde cero pensando en el hardware de hoy.

Eso es Remio. Construido de la forma difícil, porque algunas cosas valen la pena hacerlas bien.

Ícono de la app Remio

Siente la diferencia que hace lo nativo

Remio es gratis, nativo en cada plataforma y con cifrado de extremo a extremo. Huella de menos de 45 MB, unos 8 ms de procesamiento en LAN (el resto es la cadencia de actualización de 60 Hz de tu propia pantalla): construido de la forma difícil para que se sienta bien.

Gratis100% nativoCifrado de extremo a extremo