Funktionsweise von Wails
Die Architektur von Wails und die Umsetzung nativer Performance verstehen
Wails ist ein Framework zur Entwicklung von Desktopanwendungen mit Go für das Backend und Webtechnologien für das Frontend. Anders als Electron bündelt Wails jedoch keinen Browser, sondern verwendet die native WebView des Betriebssystems.
Wesentliche Unterschiede zu Electron:
| Aspekt | Wails | Electron |
|---|---|---|
| Browser | Vom Betriebssystem bereitgestellte WebView | Gebündeltes Chromium (~100 MB) |
| Backend | Go (kompiliert) | Node.js (interpretiert) |
| Kommunikation | In-Memory-Bridge | IPC (prozessübergreifend) |
| Paketgröße | ~15 MB | ~150 MB |
| Arbeitsspeicher | ~10 MB | ~100 MB+ |
| Startzeit | <0.5 s | 2-3 s |
Kernkomponenten
1. Native WebView
Wails verwendet die integrierte Web-Rendering-Engine des Betriebssystems:
WebView2 (Microsoft Edge WebView2)
- Basiert auf Chromium (wie der Edge-Browser)
- Unter Windows 10/11 vorinstalliert
- Automatische Updates über Windows Update
- Vollständige Unterstützung moderner Webstandards
WebKit (Rendering-Engine von Safari)
- In macOS integriert
- Dieselbe Engine wie der Safari-Browser
- Hervorragende Performance und Akkulaufzeit
- Vollständige Unterstützung moderner Webstandards
WebKitGTK (GTK-Portierung von WebKit)
- Installation über den Paketmanager
- Dieselbe Engine wie GNOME Web (Epiphany)
- Gute Unterstützung von Webstandards
- Ressourcenschonend und performant
Warum das wichtig ist:
- Kein gebündelter Browser → Kleinere Anwendung
- Betriebssystemnativ → Bessere Integration und Performance
- Automatische Updates → Sicherheitspatches durch Betriebssystemupdates
- Vertrautes Rendering → Wie im Systembrowser
2. Die Wails-Bridge
Die Bridge ist das Herzstück von Wails: Sie ermöglicht die direkte Kommunikation zwischen Go und JavaScript.
Funktionsweise:
- Das Frontend ruft eine Go-Methode auf (über ein automatisch generiertes Binding)
- Die Bridge codiert den Aufruf als JSON (Methodenname + Argumente)
- Der Router findet die Go-Methode in den registrierten Services
- Die Go-Methode wird ausgeführt und gibt einen Wert zurück
- Die Bridge decodiert das Ergebnis und sendet es an das Frontend zurück
- Das Promise wird aufgelöst und stellt das Ergebnis in JavaScript bereit
Performance-Eigenschaften:
- Im Arbeitsspeicher: Kein Netzwerk-Overhead, kein HTTP
- Zero-Copy, sofern möglich (bei großen Datenmengen)
- Standardmäßig asynchron: Auf beiden Seiten nicht blockierend
- Typsicher: TypeScript-Definitionen werden automatisch generiert
3. Service-System
Services sind die empfohlene Methode, um Go-Funktionalität für das Frontend bereitzustellen.
// Define a service (just a regular Go struct)
type GreetService struct {
prefix string
}
// Methods with exported names are automatically available
func (g *GreetService) Greet(name string) string {
return g.prefix + name + "!"
}
func (g *GreetService) GetTime() time.Time {
return time.Now()
}
// Register the service
app := application.New(application.Options{
Services: []application.Service{
application.NewService(&GreetService{prefix: "Hello, "}),
},
})Service-Erkennung:
- Wails untersucht Ihre Struktur beim Start
- Exportierte Methoden können vom Frontend aufgerufen werden
- Typinformationen werden für TypeScript-Bindings extrahiert
- Die Fehlerbehandlung erfolgt automatisch (Go-Fehler → JS-Ausnahmen)
Generiertes TypeScript-Binding:
// Auto-generated in frontend/bindings/GreetService.ts
export function Greet(name: string): Promise<string>
export function GetTime(): Promise<Date>Warum Services?
- Typsicher: vollständige TypeScript-Unterstützung
- Automatische Erkennung: keine manuelle Registrierung von Methoden
- Übersichtlich organisiert: zusammengehörige Funktionen gruppieren
- Testbar: Services sind einfache Go-Strukturen
4. Ereignissystem
Ereignisse ermöglichen die Pub/Sub-Kommunikation zwischen Komponenten.
Anwendungsfälle:
- Fensterkommunikation: Ein Fenster benachrichtigt andere Fenster
- Hintergrundaufgaben: Ein Go-Service informiert die Benutzeroberfläche über den Fortschritt
- Zustandssynchronisierung: mehrere Fenster synchron halten
- Lose Kopplung: Komponenten benötigen keine direkten Referenzen
Beispiel:
// Go: Emit an event
app.Event.Emit("user-logged-in", user)// JavaScript: Listen for event
import { Events } from '@wailsio/runtime'
Events.On('user-logged-in', (user) => {
console.log('User logged in:', user)
})Mehr über Ereignisse erfahren →
Anwendungslebenszyklus
Wenn Sie den Lebenszyklus verstehen, wissen Sie, wann Ressourcen initialisiert und bereinigt werden müssen.
Lebenszyklus-Hooks:
app := application.New(application.Options{
Name: "My App",
// Cleanly intercept quit requests (e.g. unsaved changes).
ShouldQuit: func() bool { return true },
// Called when the app is confirmed to be quitting — save state, close connections, etc.
OnShutdown: func() {},
})application.Options besitzt kein Feld OnStartup. Startarbeiten gehören in ServiceStartup(ctx, options) eines Services, in einen über app.Event.OnApplicationEvent(events.Common.ApplicationStarted, ...) registrierten Callback oder einfach vor app.Run().
Mehr über den Lebenszyklus erfahren →
Build-Prozess
So erstellt Wails Ihre Anwendung:
Build-Schritte:
- Go-Code analysieren
- Services nach exportierten Methoden durchsuchen
- Parameter- und Rückgabetypen extrahieren
- Methodensignaturen generieren
- TypeScript-Bindings generieren
- Für jeden Service
.ts-Dateien erstellen - Vollständige Typdefinitionen einfügen
- JSDoc-Kommentare hinzufügen
- Frontend erstellen
- Bundler ausführen (Vite, webpack usw.)
- Minifizieren und optimieren
- Ausgabe in
frontend/dist/schreiben
- Go-Code kompilieren
- Mit Optimierungen kompilieren (
-ldflags="-s -w") - Build-Metadaten einfügen
- Plattformspezifisch kompilieren
- Assets einbetten
- Frontend-Dateien in die Go-Binärdatei einbetten
- Assets komprimieren
- Eine einzelne ausführbare Datei erstellen
Ergebnis: eine einzelne native ausführbare Datei, in die alles eingebettet ist.
Mehr über das Erstellen erfahren →
Entwicklung und Produktion
Wails verhält sich in der Entwicklungs- und Produktionsumgebung unterschiedlich:
Eigenschaften:
- Hot Reload: Änderungen am Frontend werden sofort geladen
- Source Maps: Debugging mit dem ursprünglichen Quellcode
- DevTools: Browser-DevTools sind verfügbar
- Protokollierung: ausführliche Protokollierung ist aktiviert
- Externes Frontend: wird vom Entwicklungsserver bereitgestellt (Vite)
Funktionsweise:
Vorteile:
- Sofortige Rückmeldung zu Änderungen
- Umfassende Debugging-Möglichkeiten
- Schnellere Iteration
Eigenschaften:
- Eingebettete Assets: Das Frontend ist in die Binärdatei integriert
- Optimiert: minifiziert und komprimiert
- Keine DevTools: standardmäßig deaktiviert
- Minimale Protokollierung: nur Fehler
- Einzelne Datei: alles in einer ausführbaren Datei
Funktionsweise:
Vorteile:
- Verteilung als einzelne Datei
- Geringere Größe (minifiziert)
- Bessere Performance
- Keine externen Abhängigkeiten
Speichermodell
Wenn Sie die Speichernutzung verstehen, können Sie effiziente Anwendungen erstellen.
Speicherbereiche:
- Go-Heap
- Ihre Services und Ihr Anwendungszustand
- Wird vom Garbage Collector von Go verwaltet
- Bei einfachen Anwendungen typischerweise 5-10 MB
- WebView-Speicher
- DOM, JavaScript-Heap, CSS
- Wird von der WebView-Engine verwaltet
- Bei einfachen Anwendungen typischerweise 10-20 MB
- Bridge-Speicher
- Nachrichtenpuffer für die Kommunikation
- Minimaler Overhead (<1 MB)
- Wo möglich Zero-Copy für große Datenmengen
Tipps zur Optimierung:
- Vermeiden Sie die Übertragung großer Datenmengen: Übergeben Sie IDs und rufen Sie Details bei Bedarf ab
- Verwenden Sie Ereignisse für Aktualisierungen: Fragen Sie Aktualisierungen nicht vom Frontend aus regelmäßig ab
- Streamen Sie große Dateien: Laden Sie sie nicht vollständig in den Speicher
- Bereinigen Sie Listener: Entfernen Sie Ereignis-Listener, wenn sie nicht mehr benötigt werden
Mehr über Performance erfahren →
Sicherheitsmodell
Wails bietet eine standardmäßig sichere Architektur:
Sicherheitsfunktionen:
- Positivliste für Methoden
- Nur exportierte Methoden können aufgerufen werden
- Auf private Methoden kann nicht zugegriffen werden
- Services müssen explizit registriert werden
- Typvalidierung
- Argumente werden anhand der Go-Typen geprüft
- Ungültige Typen werden abgelehnt
- Verhindert Injection-Angriffe
- Kein eval()
- Das Frontend kann keinen beliebigen Go-Code ausführen
- Nur vordefinierte Methoden können aufgerufen werden
- Keine dynamische Codeausführung
- Kontextisolierung
- Jedes Fenster hat einen eigenen Kontext
- Services können den Kontext des Aufrufers prüfen
- Berechtigungen pro Fenster sind möglich
Bewährte Vorgehensweisen:
- Validieren Sie Benutzereingaben in Go (vertrauen Sie dem Frontend nicht)
- Verwenden Sie den Kontext für die Authentifizierung und Autorisierung
- Bereinigen Sie Dateipfade vor Dateioperationen
- Begrenzen Sie die Aufrufrate aufwendiger Operationen
Mehr über Sicherheit erfahren →
Nächste Schritte
Anwendungslebenszyklus – Start, Beendigung und Lebenszyklus-Hooks verstehen Mehr erfahren →
Go-Frontend-Bridge – Im Detail erfahren, wie die Bridge funktioniert Mehr erfahren →
Build-System – Verstehen, wie Wails Ihre Anwendung erstellt Mehr erfahren →
Mit der Entwicklung beginnen – Das Gelernte in einem Tutorial anwenden Tutorials →
Fragen zur Architektur? Stellen Sie sie auf Discord oder lesen Sie in der API-Referenz nach.