✦Engineering

Waarom we voor native kozen in plaats van Electron (en het weer zouden doen)

Iedereen zei dat we Electron moesten gebruiken. Eén keer bouwen, overal draaien. Snel bewegen. Wij deden het tegenovergestelde — SwiftUI op Apple, Jetpack Compose op Android, C++/WinRT op Windows, pure Metal en Vulkan waar we pixels op de klok nodig hadden. Dit leerden we van het bouwen van vier native clients voor één product.

Het gemakkelijke pad versus het juiste pad

Als je mensen vertelt dat je in 2024 een app voor extern bureaublad vanaf nul bouwt, is de eerste vraag altijd: "Waarom gebruik je niet gewoon Electron?"

Het is een terechte vraag. Electron drijft enkele van de meest succesvolle apps ter wereld aan — VS Code, Slack, Discord, de desktopverpakking van Figma. Je schrijft één keer en zet overal uit. Je webontwikkelaars worden van de ene op de andere dag desktopontwikkelaars. Het voordeel in time-to-market is echt.

We keken naar de cijfers, wogen de afwegingen en kozen het moeilijkst mogelijke pad: volledig native op elk platform. SwiftUI op iOS en macOS. Jetpack Compose op Android. C++/WinRT op Windows. Metal voor weergave op Apple. Vulkan op al het andere. Een eigen Go-server als kern.

Niet omdat we van lijden houden, al voelt het sommige dagen zo. Maar omdat native voor dit soort app geen luxe is. Het is een vereiste.

De Electron-belasting is echt

Laten we beginnen met wat Electron eigenlijk is: een Chromium-browservenster dat doet alsof het een desktopapp is. Dat is geen kritiek — het is architectuur. En voor veel toepassingen is het prima.

Maar voor extern bureaublad? Je streamt pixels van een andere computer en geeft ze in realtime weer, terwijl je elke invoergebeurtenis vastlegt en terugstuurt. Latentie is geen extraatje. Het is het hele product.

Dit maten we toen we beide benaderingen prototypeden:

De 380 MB is niet Electron dat opgeblazen is. Het is Chromium dat zijn werk doet — V8, een gpu-proces, hulpprocessen, een complete browserengine. Het is indrukwekkende techniek. Het is alleen techniek die is ontworpen voor een ander probleem.

Frames tellen zwaarder dan functies

Extern bureaublad is een van de weinige app-categorieën waarin elk afzonderlijk frame telt. Mis een frame en de gebruiker voelt het. Voeg 16 ms invoerlatentie toe en een ontwerper kan geen vloeiende curves meer tekenen. Voeg 32 ms toe en een gamer kan niet meer spelen.

Met native weergave praten we rechtstreeks met de gpu. Op Apple-platforms geeft VideoToolbox ons directe toegang tot hardwarematige videodecodering. We halen een H.265-frame van het netwerk, decoderen het in hardware en tonen het — zonder dat het frame ooit het hoofdgeheugen aanraakt. De pijplijn van decoderen tot tonen draait op een moderne Mac in minder dan 4 ms.

In Electron reist datzelfde frame door de compositor van Chromium, door de IPC-brug, wordt het getekend door Skia en daarna opnieuw samengesteld door het besturingssysteem. Elke stap voegt latentie toe. Elke stap voegt jitter toe. En jitter — onregelmatige frametiming — is wat extern bureaublad niet goed laat aanvoelen, ook als het gemiddelde aantal FPS er prima uitziet.

We kozen niet voor native uit zuiverheid. We kozen het omdat de natuurkunde van ons probleem erom vroeg — zo'n 8 ms verwerking op een lokaal netwerk (de rest is de eigen verversingsfrequentie van 60 Hz van je scherm) laat geen ruimte voor een browser in het midden.

Overzicht van mogelijkheden: native versus web

Het debat Electron versus native blijft vaak steken in gevoel. Dus schreven we de zeven mogelijkheden van het besturingssysteem op waar Remio elke seconde van elke sessie van afhangt, en vroegen we eenvoudig: hoe doet elk ervan het onder elke runtime?

MogelijkheidNativeWeb / Electron
Hardwarematige decodering op 60 fps● Direct VideoToolbox / D3D11VA○ Via WebCodecs, jitter
USB-audio met lage latentie● CoreAudio / WASAPI— Gesandboxed, 40 ms+
Toetsenbordinvoer bewaken● CGEvent / SendInput— Geblokkeerd buiten focus
Gpu-toegang met Metal / D3D11● Zero-copy-textures○ WebGPU, kopieerstappen
Lokaal bestandssysteem● Volledig, begrensd door het besturingssysteem○ Alleen kiezer, meldingen
Meerdere vensters, meerdere schermen● Vensterbeheer van het besturingssysteem○ BrowserWindow-shims
Blijven draaien op de achtergrond● LaunchAgent / service— Opgeschort bij verbergen

Elke rij is een functie die we vandaag leveren. Elk — in de webkolom is een omweg die we zouden moeten verzinnen, documenteren en waarvoor we onze excuses zouden moeten aanbieden. Native gaan betekent dat we die mogelijkheden als bouwstenen behandelen in plaats van als polyfills.

Burgerschap op het platform

Dit is iets waar het publiek van schrijf-één-keer-draai-overal zelden over praat: gebruikers merken het.

Ze merken het wanneer een app de overgangen van de systeem-donkere modus niet respecteert. Wanneer de scrollfysica net niet klopt. Wanneer de app niet in Spotlight verschijnt of het vensterbeheer van macOS niet goed afhandelt. Wanneer het contextmenu eruitziet als een webpagina in plaats van een native menu.

Dit zijn geen extraatjes. Ze zijn het verschil tussen een app die mensen dulden en een app waar mensen van houden. Op iOS is dit extra cruciaal — de beoordeling van de App Store wijst apps af die niet native aanvoelen, en terecht.

Met SwiftUI krijgen we dit allemaal gratis. Dynamic Type, toegankelijkheid met VoiceOver, systeemhaptiek, multitasken op iPad, sneltoetsen op Mac. We bouwen geen platformfuncties opnieuw. We gebruiken ze.

De kosten zijn ook echt

Laten we eerlijk zijn over de keerzijde: native gaan is duur. Niet in dollars — in tijd en complexiteit.

We onderhouden vier UI-codebases. Onze netwerk- en codeclaag wordt gedeeld (Go voor signalering, C++ voor het streamingprotocol), maar elke pixel die je op het scherm ziet, is platformspecifieke code. Een functie die in Electron een dag kost, kost ons drie tot vijf dagen, omdat we hem vier keer bouwen, afgesteld op elk platform.

We hebben weken gehad waarin één enkele animatie prachtig werkte op iOS, kapot was op Android en haperde op Windows. De debugmatrix is moordend.

Maar dit leerden we: het moeilijkste pad en het juiste pad zijn vaak hetzelfde pad. Onze gebruikers kennen onze architectuur niet en geven er niet om. Ze weten dat Remio snel voelt, goed voelt en hun batterij niet als ontbijt opeet.

Zouden we het weer doen

Zonder aarzelen.

De native aanpak gaf ons prestaties waar Electron voor dit gebruik fundamenteel niet aan kan tippen. Het gaf ons apps die aanvoelen alsof ze op elk platform thuishoren. Het gaf ons een geheugengebruik onder 45 MB in plaats van 380 MB. Het gaf ons zo'n 8 ms verwerking op een lokaal netwerk (de rest is de eigen verversingsfrequentie van 60 Hz van je scherm), waar een concurrent in een browserverpakking boven de 60 ms zit.

Het belangrijkste: het gaf ons een technische gracht. Native bouwen op vier platforms is zo moeilijk dat de meeste concurrenten het niet zullen doen. Die moeilijkheid is ons voordeel.

De categorie extern bureaublad werd gedomineerd door webapps in een Electron-verpakking en oude native apps die al jaren niet meer betekenisvol zijn bijgewerkt. Er is ruimte voor iets dat zowel modern als native is — iets dat vanaf nul is gebouwd met de hardware van vandaag in gedachten.

Dat is Remio. Op de moeilijke manier gebouwd, omdat sommige dingen het waard zijn om goed te doen.

App-icoon van Remio

Voel het verschil dat native maakt

Remio is gratis, native op elk platform en end-to-end versleuteld. Geheugengebruik onder 45 MB, zo'n 8 ms verwerking op een lokaal netwerk (de rest is de eigen verversingsfrequentie van 60 Hz van je scherm) — op de moeilijke manier gebouwd zodat het goed aanvoelt.

Gratis te gebruiken100% nativeEnd-to-end versleuteld