Wails: Golangs Wette auf Desktop-Apps, um Electron zu schlagen

BBetter Stack
Computing/SoftwareInternet Technology

Transcript

00:00:00Wails ist eine plattformübergreifende Technologie, mit der man Desktop-Apps in Go entwickeln kann.
00:00:04Nach meinen vielen Desktop-Vergleichsvideos wurde das im Kanal extrem oft angefragt.
00:00:08Heute zeige ich euch also, wie man mit Wails echte Desktop-Apps baut,
00:00:13und vergleiche es mit Frameworks wie Electron und Tauri. Wir gehen schrittweise durch den Bau
00:00:17eines Desktop-Bildschirmrecorders, wie in anderen Videos, und vergleichen Dateigröße,
00:00:22Performance und Developer Experience. Wails ist für mich völlig neu, wir lernen hier also
00:00:27gemeinsam dazu. Wails funktioniert im Grunde genau wie Tauri, nur dass das
00:00:36Backend in Go statt Rust geschrieben ist. Das Frontend baut man weiterhin in einer WebView mit Webtechnologien
00:00:41und ruft native APIs auf, die von Go verwaltet werden. So kann man eine Anwendung kompilieren,
00:00:47die sowohl mit Mac als auch Windows kompatibel ist. Anders als Electron bettet Wails jedoch keinen Browser ein.
00:00:52Stattdessen nutzt es wie Tauri die native Rendering-Engine der jeweiligen Plattform. Die Bundle-Größe
00:00:58sollte theoretisch also viel kleiner sein, aber das sehen wir uns später beim Vergleich genauer an.
00:01:03Wenn euch solcher Content gefällt, abonniert gerne den Kanal. Das hier ist das Bildschirmaufnahme-Tool,
00:01:07das ich mit Wails entwickelt habe – und dasselbe habe ich auch in Electron und Tauri gebaut.
00:01:12Wir wählen den Bildschirm aus, den wir aufnehmen wollen, und klicken auf Aufnahme. Man kann die Maus bewegen.
00:01:16Die Desktop-App selbst erscheint nicht in der Aufnahme. Ich klicke auf Stopp, und schon sieht man das
00:01:21gerade aufgenommene Video. Ich könnte es jetzt noch schneiden und dann einfach auf MP4-Export klicken,
00:01:27um das Video direkt auf meinem Rechner zu speichern. Wenn wir uns die Struktur des Projekts ansehen,
00:01:32sieht man ein sehr ähnliches Setup wie bei Electron. Alle Frontend-Dateien liegen in einem Frontend-Ordner,
00:01:36und dann haben wir die Einstiegsdatei. In diesem Fall ist es eine Go-Datei namens main.go, und hier drin
00:01:41befindet sich eine main-Funktion. Auch das kennt man ähnlich aus Electron. Wir können Dinge wie
00:01:47Titel, Breite und Höhe festlegen, die Hintergrundfarbe einstellen und spezifische Optionen
00:01:52für Mac definieren. Unterschiede zwischen Mac und Windows einzubauen, ist also problemlos
00:01:57möglich. Schauen wir jetzt in den Frontend-Ordner unter src, finden wir den gesamten
00:02:02React-Code. Wenn wir in app.tsx schauen, ist das ganz normaler React-Code, abgesehen davon, dass wir
00:02:09APIs aufrufen, die auf der Go-Seite definiert sind. Betrachten wir den Import API und dessen Verwendung
00:02:16in der Datei: Wir nutzen API.onrecording finished, onrecording failed, start recording, und diese API wird
00:02:22automatisch von Wails generiert. Blicken wir in die API selbst, sehen wir, dass alle Kernfunktionen
00:02:27aus dieser Datei hier stammen: wails.js/go/main/app. Wenn wir hier reinsehen,
00:02:33erkennt man, dass die Datei automatisch generiert wurde. Oben steht Walisisch und darunter Englisch,
00:02:39denn – ob ihr es glaubt oder nicht – der Entwickler von Wails ist Waliser. Hier haben wir all diese Funktionen
00:02:43wie export video, list sources, request screen access – alles, was man für ein
00:02:49Screen-Recording-Tool braucht. Wenn wir jetzt auf die Go-Seite in app.go wechseln und dort
00:02:54list sources auskommentieren und speichern, erhalten wir sofort einen Fehler in API.ts, weil
00:02:59list sources nicht mehr existiert. Das liegt daran, dass wails.dev läuft: Bei jeder Änderung
00:03:05in der Go-Datei werden die TypeScript-Definitionen automatisch neu gerendert. Machen wir das rückgängig und
00:03:11kommentieren es wieder ein, verschwindet der Fehler und die Desktop-App lädt sich neu,
00:03:16da alle Änderungen von der Go-Seite – also dem Backend – die Anwendung automatisch neu kompilieren
00:03:23und rendern. Machen wir nun ein paar Vergleiche, um die Unterschiede der drei Frameworks zu sehen.
00:03:27Zuerst die Bundle-Größe: Wails liegt bei 52 Megabyte, Tauri bei 57 Megabyte und Electron
00:03:34wenig überraschend bei 324 Megabyte. Wails und Tauri sind hier spürbar kleiner, da sie
00:03:41kein Chromium mitliefern – das war also zu erwarten. Ich würde allerdings sagen, dass durch die Nutzung
00:03:47der nativen WebView der jeweiligen Plattform, wie Wails und Tauri es tun, eher Plattformunterschiede auftreten können.
00:03:51Das ist heutzutage zwar kaum noch ein Problem, aber man sollte es im Hinterkopf behalten. Im Grunde liefern Tauri und
00:03:57Wails also ähnliche Ergebnisse bei der Bundle-Größe, da beide Frameworks trotz völlig unterschiedlicher
00:04:02Technologien unter der Haube sehr ähnlich aufgebaut sind.
00:04:07Werfen wir nun einen Blick auf die Startzeit. Wie in meinen früheren Videos zu Desktop-Apps
00:04:12starten wir jede App 10-mal und nehmen den Mittelwert. Wails benötigt 395
00:04:18Millisekunden, Tauri 410 Millisekunden und Electron 350 Millisekunden. Bei Kaltstarts,
00:04:26bei denen wir den Cache jedes Mal leeren, kommt Wails auf 2.337 ms, Tauri auf 2.049 ms und Electron ist mit
00:04:341.890 ms tatsächlich etwas schneller. Zur Performance: Genau wie bei Tauri ist die Laufzeit-Performance bei der
00:04:40Bildschirmaufnahme viel besser als bei Electron. Das liegt an unserem Aufbau, bei dem wir das
00:04:45native ScreenCaptureKit von Mac nutzen, sodass keine Daten über die Bridge fließen. Bei Electron nehmen wir direkt
00:04:51aus der WebView auf und leiten die Daten an das Backend weiter, was etwas Overhead erzeugt.
00:04:56Theoretisch könnte man auch bei Electron das native ScreenCaptureKit nutzen, indem man eigenen C-Code schreibt,
00:05:02aber die gezeigte Variante ist der Standardweg in Electron, weshalb wir ihn heute vergleichen.
00:05:06Schauen wir uns nun die Developer Experience an – hier zeigen sich die größten
00:05:11Unterschiede. Das Entwickeln mit Wails hat mir wirklich Spaß gemacht, allerdings war der Teil mit der
00:05:15Bildschirmaufnahme nicht so einfach wie bei Tauri. Ich musste Objective-C-Code schreiben, um auf das ScreenCaptureKit zuzugreifen,
00:05:21während man bei Tauri komplett in Rust bleiben konnte. Das liegt daran, dass Rust ein großes Ökosystem an
00:05:28Community-Crates bietet, die Apples native Frameworks einbinden. In Tauri habe ich einfach ein Crate namens
00:05:33screencapturekit eingebunden, und die gesamte Aufnahme-API war ganz normales Rust. Für Go habe ich nichts Brauchbares
00:05:39für ScreenCaptureKit gefunden, aber es gibt Cgo – Gos integrierte Möglichkeit, C-Code zu kompilieren.
00:05:44Das bedeutet, dass man in Go natives C in einer .m-Datei schreiben, als einfache C-Funktionen bereitstellen und
00:05:50Go mitteilen kann, welche Apple-Frameworks verknüpft werden sollen. Am Ende schreibt man also echtes Objective-C
00:05:56und ruft dieselben Apple-APIs wie das Rust-Crate auf, besitzt dafür aber den gesamten Code selbst.
00:06:02Das waren letztlich etwa 450 Zeilen Objective-C-Code, die bei der Rust-App gar nicht nötig waren. Insgesamt
00:06:08neige ich daher etwas mehr zu Tauri. Das Ökosystem rund um die Rust-Crates ist nach meiner Erfahrung besser,
00:06:14aber am Ende ist es reine Geschmackssache. Wenn ihr gerne in Go entwickelt, ist Wails eine wirklich
00:06:18gute Wahl, und wenn ihr Rust mögt, wählt einfach Tauri. Falls ihr euch für Wails entscheidet, müsst ihr jedoch eventuell
00:06:24etwas nativen Code schreiben, da das Ökosystem noch nicht so etabliert ist. Ich hoffe, das Video hat euch gefallen
00:06:29und ihr abonniert für mehr Content dieser Art. Und wenn ihr weitere Vergleichsvideos
00:06:33zu Desktop-Frameworks sehen wollt, wie etwa unseren Vergleich von Deno Desktop und Electrobun: Ich habe hier direkt
00:06:39ein Video verlinkt, das ihr euch ansehen könnt. Ansonsten vielen Dank fürs Zuschauen! Ich bin Warren von Better Stack
00:06:43und wir sehen uns im nächsten Video. Und leider hat Milo gesagt, keine Videos mehr für diese Woche, also
00:06:49sehen wir uns am Montag.
00:06:50*Musik spielt*

Key Takeaway

Wails bietet eine Go-basierte Alternative zu Tauri mit minimaler Bundle-Größe von 52 MB, erfordert bei plattformspezifischen APIs wie ScreenCaptureKit mangels fertiger Go-Crates jedoch manuellen Cgo- und Objective-C-Code.

Highlights

  • Wails erzeugt eine Bundle-Größe von 52 MB, während Tauri 57 MB und Electron 324 MB benötigen.

  • Bei der Startzeit benötigt Wails 395 ms, Tauri 410 ms und Electron 350 ms im Durchschnitt von 10 Versuchen.

  • Kaltstarts nach Cache-Leerung dauern 2.337 ms bei Wails, 2.049 ms bei Tauri und 1.890 ms bei Electron.

  • Änderungen in Go-Dateien lösen über wails.dev das automatische Neu-Generieren der TypeScript-Definitionen und die Re-Kompilierung aus.

  • Für den Zugriff auf das macOS ScreenCaptureKit erfordert Wails etwa 450 Zeilen eigenen Objective-C-Code über Cgo, da vorgefertigte Go-Bibliotheken fehlen.

Timeline

Funktionsweise und Architektur von Wails

  • Wails kombiniert ein Go-Backend mit einem Web-Frontend über die native WebView des jeweiligen Betriebssystems.
  • Der Verzicht auf ein mitgeliefertes Chromium reduziert die Anwendungsgröße im Vergleich zu Electron erheblich.
  • Cross-Platform-Anwendungen für macOS und Windows entstehen aus einer gemeinsamen Codebasis.

Die Architektur gleicht Tauri, nutzt aber Go anstelle von Rust für logische Operationen und Systemaufrufe. Das User Interface läuft in einer nativen WebView der Zielplattform. Eine funktionale Bildschirmaufzeichnungs-App demonstriert die Integration von Frontend-Steuerung und nativem Video-Export.

Projektstruktur und automatische API-Generierung

  • Der Go-Einstiegspunkt main.go steuert Fensterparameter wie Titel, Abmessungen und plattformspezifische Stile.
  • Aktivierte Entwicklerserver synchronisieren Go-Backend-Funktionen automatisch mit generierten TypeScript-Typisierungen.
  • Backend-Änderungen lösen sofortige Kompilierung und Frontend-Aktualisierungen aus.

Frontend-Dateien liegen isoliert im src-Ordner und greifen über automatisch erzeugtes JavaScript direkt auf Go-Methoden zu. Das Entfernen einer Go-Funktion führt sofort zu einem TypeScript-Kompilierfehler im Frontend. Diese Kopplung sichert Typsicherheit über die Prozessgrenze hinweg.

Leistungsvergleich: Wails, Tauri und Electron

  • Wails erzielt mit 52 MB das kleinste Anwendungs-Bundle vor Tauri mit 57 MB und Electron mit 324 MB.
  • Warmstarts dauern bei Wails 395 ms, während Electron bei Kaltstarts mit 1.890 ms die schnellste Zeit erreicht.
  • Native API-Einbindungen vermeiden Performance-Overhead bei der Datenübertragung zwischen Frontend und Backend.

Die Verwendung systemeigener WebViews hält die Dateigröße von Wails und Tauri auf etwa einem Sechstel von Electron. Bei der Bildschirmaufzeichnung nutzt Wails direkt das ScreenCaptureKit von macOS. Dadurch entfällt das Streamen großer Datenmengen über die IPC-Bridge, was die Prozessorlast im Vergleich zum Standard-Prozess von Electron senkt.

Entwicklererfahrung und Integration nativer Schnittstellen

  • Fehlende Go-Bibliotheken für macOS-System-APIs erfordern den Einsatz von Cgo und Objective-C.
  • Tauri bietet durch das umfangreichere Rust-Crate-Ökosystem direkteren Zugriff auf Betriebssystem-Schnittstellen.
  • Wails eignet sich für Entwickler mit Go-Fokus, erfordert bei tiefen Systemintegrationen jedoch eigenen C-Code.

In Tauri deckt das Rust-Crate screencapturekit die macOS-Aufnahme ohne Zusatzcode ab. Für Wails mussten 450 Zeilen Objective-C in einer .m-Datei geschrieben und via Cgo eingebunden werden. Die Sprachpräferenz für das Backend entscheidet maßgeblich über die Wahl zwischen Wails und Tauri.

Community Posts

View all posts