Zurück zum Blog

Schluss mit Electron, nimm Wails: Desktop-Apps mit Go 2026

Wails ist die Electron-Alternative für Desktop-Apps in Go. Eine leere App hat 8 bis 11 MB statt 295 bis 384 MB. Wo Wails gewinnt, wo Electron vorn bleibt.

Schluss mit Electron, nimm Wails: Desktop-Apps mit Go 2026

Wenn du ein internes Tool, einen Datenbank-Client, einen Log-Viewer oder irgendeine kleine bis mittelgroße Desktop-App baust, nimm Wails statt Electron. Wails kombiniert ein Go-Backend mit der Webview, die das Betriebssystem ohnehin mitbringt. Eine leere App landet so bei etwa 8 bis 11 MB statt bei 295 bis 384 MB (Elanis-Benchmark, 2026). Dein Web-Frontend behältst du und ersetzt nur Node durch Go. Aus handgeschriebenem IPC werden generierte Bindings, und ein mitgeliefertes Chromium gibt es nicht, weil das Betriebssystem die Webview stellt. Wails gewinnt allerdings nicht jeden Benchmark, und für manche Apps ist Electron weiterhin die bessere Wahl.

Kurzfassung

  • Bei der Größe gewinnt Wails klar. In einem CI-Benchmark mit leeren Apps waren Wails-Builds unter Windows, macOS und Linux 30- bis 40-mal kleiner als Electron-Builds (Elanis-Benchmark, 2026).
  • Bei Speicher und Startzeit ist das Bild gemischt. Wails brauchte unter macOS und Linux weniger Speicher, unter Windows aber mehr. Electron startete im selben Benchmark auf allen drei Betriebssystemen schneller.
  • Die größeren Vorteile liegen in der Architektur. Du lieferst ein einziges Go-Binary aus, schreibst das Backend mit Gos Standardbibliothek und goroutines, rufst es über typisierte, generierte Bindings auf und hast kein Node in der Seite.
  • Du jagst keinen Electron-Major-Versionen mehr hinterher. Electron veröffentlicht alle 8 Wochen eine neue Major-Version und unterstützt nur die drei neuesten (Electron, 2026). Bei Wails wird die Webview außerhalb deiner App gepatcht: unter Windows durch den Evergreen-WebView2-Updater (Microsoft Learn, 2026), unter macOS durch System-Updates und unter Linux durch die Pakete deiner Distribution.
  • Electron bleibt die richtige Wahl, wenn du überall exakt gleiches Chromium-Rendering brauchst, von nativen Node-Modulen abhängst oder schon eine große Electron-Codebasis hast.

Was liefert Electron mit jeder App aus?

Jede Electron-App bringt ihren eigenen Browser und ihre eigene JavaScript-Runtime mit. In der Electron-Doku heißt es: „Durch das Einbetten von Chromium und Node.js in sein Binary ermöglicht es Electron dir, eine einzige JavaScript-Codebasis zu pflegen“, und zwar plattformübergreifend (Electron-Doku, 2026). Dieser Deal war sinnvoll, als die Alternative drei native Codebasen waren. Er bedeutet aber auch, dass jede App, die du installierst, eine komplette Kopie von Chromium mitschleppt.

Auch das Prozessmodell stammt von Chromium. Es gibt einen Hauptprozess, in dem Node.js läuft, dazu „einen separaten Renderer-Prozess für jedes offene BrowserWindow (und jedes Web-Embed)“ (Electron-Prozessmodell, 2026). Deine Backend-Logik lebt im Hauptprozess, deine UI in den Renderern, und verbunden werden beide über IPC-Nachrichten, die du von Hand schreibst.

Dazu kommt der Release-Zyklus. „Der Abstand zwischen Electrons Major-Releases beträgt 8 Wochen“, und unterstützt werden nur die drei neuesten stabilen Major-Versionen (Electron-Zeitplan, 2026). Electron 44.0.0 wurde am 25. August 2026 stabil, mit Chromium M152 und Node v24.18.1. Electron 45 ist für den 20. Oktober 2026 geplant (Electron-Releases, 2026). Damit Chromium-Sicherheitsfixes bei deinen Usern ankommen, musst du in diesem Takt immer wieder neue Builds ausliefern.

Wie funktioniert Wails?

Wails beschreibt sich selbst als „eine leichtgewichtige und schnelle Electron-Alternative für Go“ (Wails-Doku, 2026). Statt einen Browser mitzuliefern, „nutzt es die native Rendering-Engine der jeweiligen Plattform“. Im README steht: „Nutzt native Rendering-Engines, kein eingebetteter Browser!“ (Wails auf GitHub, 2026). Welche Engine das ist, hängt vom Betriebssystem ab:

  • Windows rendert deine UI mit Microsoft WebView2.
  • macOS rendert sie mit WebKit.
  • Linux rendert sie mit WebKitGTK.

Eine Wails-App ist „eine normale Go-Anwendung mit einem WebKit-Frontend“ (How Wails works, 2026). Dein Frontend (React, Svelte, Vue oder schlichtes HTML) wird per //go:embed in das Go-Binary eingebettet, sodass die ganze App als eine einzige ausführbare Datei ausgeliefert wird.

Die Brücke zwischen beiden Hälften ist die Option Bind, die „festlegt, welche Struct-Methoden für das Frontend freigegeben werden“. Wenn du wails dev ausführst, liest Wails diese Methoden aus und generiert JavaScript-Wrapper plus TypeScript-Deklarationen. Dein Frontend ruft Go-Methoden auf wie async-Funktionen. In die andere Richtung sendet Go Runtime-Events, und JavaScript hört darauf.

Wails v2 ist die stabile Linie, v2.14.0 erschien am 10. August 2026 (Wails-Releases, 2026). Das Projekt steht unter MIT-Lizenz und hat rund 36.300 GitHub-Sterne. Zu den Apps, die darauf aufbauen, gehören Tiny RDM, eine Redis-GUI mit rund 13.000 Sternen (Tiny RDM, 2026), und der gRPC-Client Wombat (Wails-Showcase, 2026).

Wails vs Electron: Wie viel kleiner und leichter ist die App?

Viel kleiner, aber nicht immer leichter. Die besten öffentlichen Zahlen liefert der Elanis-Vergleich von Web-to-Desktop-Frameworks. Er baut in jedem Framework eine leere App im Release-Modus auf GitHub CI und misst Größe, Speicher und Startzeit. Zuletzt aktualisiert wurde er am 4. September 2026 (Elanis-Benchmark, 2026).

Balkendiagramm der Build-Größe einer leeren App bei Wails vs Electron nach Betriebssystem: Electron etwa 295 bis 384 MB, Wails etwa 8 bis 11 MB, Tauri etwa 3 bis 5 MB

MetrikOSElectronWailsTauri
Build-GrößeWindows x64~384 MB~11 MB~3 MB
Build-GrößemacOS arm64~319 MB~8 MB~5 MB
Build-GrößeLinux x64~295 MB~9 MB~4 MB
SpeicherWindows x64~278 MB~323 MB~317 MB
SpeichermacOS arm64~369 MB~100 MB~95 MB
SpeicherLinux x64~586 MB~360 MB~94 MB
StartzeitWindows x64~206 ms~559 ms~711 ms
StartzeitmacOS arm64~640 ms~1.740 ms~2.044 ms
StartzeitLinux x64~204 ms~263 ms~30.325 ms

Quelle: Elanis web-to-desktop-framework-comparison, aktualisiert am 04.09.2026. Leere App, Release-Build, GitHub CI. Vergleiche Frameworks nur innerhalb desselben Betriebssystems. Das README nennt keine Framework-Versionen.

Bei der Größe gewinnt Wails eindeutig. Eine leere Wails-App ist unter Windows etwa 35-mal kleiner als Electron, unter macOS 40-mal und unter Linux 33-mal. Über ein langsames Hotel-WLAN sind 11 MB in Sekunden geladen, 384 MB dauern Minuten. Und es summiert sich, wenn jedes Tool auf einem Laptop sein eigenes Chromium mitbringt.

Beim Speicher kommt es auf das Betriebssystem an. Unter macOS brauchte Wails etwa 3,7-mal weniger Speicher als Electron. Unter Linux waren es etwa 1,6-mal weniger. Unter Windows brauchte Wails mehr, etwa 323 MB gegenüber 278 MB bei Electron. Der Benchmark schlüsselt das nicht auf, aber WebView2 nutzt die Engine von Microsoft Edge, die auf Chromium basiert, und startet eigene Browser-Prozesse. Unter Windows zahlst du also wahrscheinlich trotzdem Speicher für eine Chromium-Engine, auch wenn du keine mitlieferst.

Electron startete in diesem Benchmark überall schneller. Unter Windows lag Electron bei etwa 206 ms, Wails bei 559 ms. Unter macOS stand es 640 ms zu 1.740 ms. Unter Linux lagen beide nah beieinander, 204 ms zu 263 ms. Eine leere App auf einem CI-Runner ist nur ein grober Anhaltspunkt und entspricht nicht dem, was deine User sehen. Dass Wails immer schneller startet, geben die Daten trotzdem nicht her.

Noch ein Vorbehalt für Windows. Wails-Apps brauchen die Microsoft WebView2 Runtime. Sie ist in Windows 11 enthalten, und laut Microsoft ist „die WebView2 Runtime auf der überwiegenden Mehrheit der Windows-10-Geräte bereits installiert“ (Microsoft Learn, 2026). Für den Rest bettest du den Bootstrapper ein, was etwa 150 KB zusätzlich kostet (Wails-Windows-Guide, 2026). Brauchst du dagegen eine fest gepinnte Engine, warnt Microsoft: „Die Fixed-Version-Binaries sind über 250 MB groß und machen dein App-Paket um genau diese Menge größer.“ Damit ist der Größenvorteil unter Windows größtenteils dahin.

Wie sieht Wails-Code aus?

Hier ist ein kleiner Log-Viewer, wie du ihn für dein Team bauen könntest: Log-Datei auswählen, die letzten 200 Zeilen anzeigen und dann neue Zeilen streamen, sobald sie geschrieben werden. Außerdem pingt er den Health-Endpoint eines Services an. Die ganze Logik läuft in Go, das Frontend rendert nur.

Die Go-Seite ist ein ganz normales Struct mit exportierten Methoden. TailLog liest eine Datei mit os und bufio. CheckHealth ruft mit net/http einen HTTP-Endpoint mit Timeout auf, genau das behandelt der HTTP-Kurs. Der folgende Code kompiliert gegen Wails v2.14.0:

example.gogo
// app.go
package main

import (
	"bufio"
	"context"
	"fmt"
	"net/http"
	"os"
	"sync"
	"time"
)

const tailLines = 200

type App struct {
	ctx        context.Context
	mu         sync.Mutex
	stopFollow context.CancelFunc
}

func NewApp() *App { return &App{} }

// startup is called by Wails once the app is running. Keep the context:
// runtime calls like EventsEmit need it.
func (a *App) startup(ctx context.Context) {
	a.ctx = ctx
}

// TailLog returns the last 200 lines of the log file at path.
func (a *App) TailLog(path string) ([]string, error) {
	f, err := os.Open(path)
	if err != nil {
		return nil, fmt.Errorf("open log: %w", err)
	}
	defer f.Close()

	lines := make([]string, 0, tailLines)
	sc := bufio.NewScanner(f)
	sc.Buffer(make([]byte, 0, 64*1024), 1024*1024) // allow long JSON log lines
	for sc.Scan() {
		if len(lines) == tailLines {
			lines = lines[1:]
		}
		lines = append(lines, sc.Text())
	}
	if err := sc.Err(); err != nil {
		return nil, fmt.Errorf("read log: %w", err)
	}
	return lines, nil
}

// CheckHealth calls a service's health endpoint and returns the status code.
func (a *App) CheckHealth(url string) (int, error) {
	ctx, cancel := context.WithTimeout(a.ctx, 3*time.Second)
	defer cancel()

	req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
	if err != nil {
		return 0, fmt.Errorf("build request: %w", err)
	}
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return 0, fmt.Errorf("health check %s: %w", url, err)
	}
	defer resp.Body.Close()
	return resp.StatusCode, nil
}

main bettet das gebaute Frontend ein und übergibt das Struct an Bind. Wails v2 liegt unter github.com/wailsapp/wails/v2:

example.gogo
// main.go
package main

import (
	"embed"
	"log"

	"github.com/wailsapp/wails/v2"
	"github.com/wailsapp/wails/v2/pkg/options"
	"github.com/wailsapp/wails/v2/pkg/options/assetserver"
)

//go:embed all:frontend/dist
var assets embed.FS

func main() {
	app := NewApp()

	err := wails.Run(&options.App{
		Title:  "Log Viewer",
		Width:  1100,
		Height: 720,
		AssetServer: &assetserver.Options{
			Assets: assets,
		},
		OnStartup: app.startup,
		Bind:      []interface{}{app},
	})
	if err != nil {
		log.Fatal(err)
	}
}

Führ wails dev aus, und Wails generiert frontend/wailsjs/go/main/App.js und App.d.ts. Die Deklarationen sehen so aus:

example.tsts
export function TailLog(arg1: string): Promise<Array<string>>;
export function CheckHealth(arg1: string): Promise<number>;

Jede gebundene Methode gibt ein Promise zurück. Liefert die Go-Methode einen error ungleich nil, wird das Promise damit rejected. Das Frontend kommt also mit ganz normalem await und try/catch aus:

example.tsts
import { TailLog, CheckHealth } from "../wailsjs/go/main/App";

async function openLog(path: string) {
  try {
    const lines = await TailLog(path);
    renderLines(lines);
  } catch (err) {
    showError(`Could not read ${path}: ${err}`);
  }
}

async function refreshStatus(url: string) {
  try {
    const status = await CheckHealth(url);
    setStatus(status === 200 ? "healthy" : `HTTP ${status}`);
  } catch (err) {
    setStatus(`down: ${err}`);
  }
}

Du musst weder Channel-Namen synchron halten noch Nachrichtenformate von Hand prüfen. Änderst du die Signatur einer Go-Methode, ändert sich die neu generierte Deklaration mit. Ein typgeprüfter Frontend-Build markiert dann die veralteten Aufrufe.

Neue Zeilen mit Runtime-Events streamen

Beim Mitlesen einer Live-Datei zahlt sich Gos Nebenläufigkeit aus. FollowLog springt ans Ende der Datei, danach fragt eine goroutine regelmäßig nach neuen Zeilen und schickt jede per runtime.EventsEmit ans Frontend. Wird eine andere Datei geöffnet, bricht das den vorherigen Follower ab:

example.gogo
// follow.go
package main

import (
	"bufio"
	"context"
	"fmt"
	"io"
	"os"
	"strings"
	"time"

	"github.com/wailsapp/wails/v2/pkg/runtime"
)

// FollowLog streams lines appended to path as "log:line" events.
func (a *App) FollowLog(path string) error {
	f, err := os.Open(path)
	if err != nil {
		return fmt.Errorf("open log: %w", err)
	}
	if _, err := f.Seek(0, io.SeekEnd); err != nil {
		f.Close()
		return fmt.Errorf("seek log: %w", err)
	}

	a.mu.Lock()
	if a.stopFollow != nil {
		a.stopFollow()
	}
	ctx, cancel := context.WithCancel(a.ctx)
	a.stopFollow = cancel
	a.mu.Unlock()

	go a.follow(ctx, f)
	return nil
}

func (a *App) follow(ctx context.Context, f *os.File) {
	defer f.Close()

	r := bufio.NewReader(f)
	var partial strings.Builder
	ticker := time.NewTicker(500 * time.Millisecond)
	defer ticker.Stop()

	for {
		select {
		case <-ctx.Done():
			return
		case <-ticker.C:
			for {
				chunk, err := r.ReadString('\n')
				partial.WriteString(chunk)
				if err != nil {
					break // no complete line yet, try again on the next tick
				}
				line := strings.TrimRight(partial.String(), "\r\n")
				runtime.EventsEmit(a.ctx, "log:line", line)
				partial.Reset()
			}
		}
	}
}

Im Frontend abonnierst du einmal mit EventsOn:

example.tsts
import { FollowLog } from "../wailsjs/go/main/App";
import { EventsOn } from "../wailsjs/runtime/runtime";

EventsOn("log:line", (line: string) => appendLine(line));

await FollowLog("/var/log/payments-api/app.log");

In Electron würdest du dasselbe Feature mit fs im Hauptprozess schreiben, dazu ein ipcMain.handle für das Lesen, ein webContents.send für jede neue Zeile und ein Preload-Skript, das beides über contextBridge freigibt. In Wails sind es ein Go-Struct und ein Event-Name. Diese Version kümmert sich nicht um Log-Rotation. Ein Follower für die Produktion würde die Datei neu öffnen, sobald ihre Größe schrumpft.

Wails v3 ändert die Form ein wenig. Du registrierst Services in application.Options.Services mit application.NewService(&LogService{}), und das Frontend importiert generierten Code aus einem bindings-Verzeichnis statt aus wailsjs (Wails-v3-Bindings, 2026). Was das Frontend aufruft, sind weiterhin Methoden auf einem Go-Typ.

Wie unterscheidet sich das Sicherheitsmodell?

Die Sicherheit von Electron hängt an einer Checkliste, Wails startet mit einer kleineren Angriffsfläche. Electrons eigener Security-Guide verlangt, dass du Node-Integration für Remote-Inhalte ausgeschaltet lässt (Standard seit 5.0.0), Context Isolation eingeschaltet lässt (Standard seit 12.0.0), Prozess-Sandboxing eingeschaltet lässt (Standard seit 20.0.0), den Absender jeder IPC-Nachricht prüfst, eine Content Security Policy setzt und APIs nur über contextBridge für die Seite freigibst (Electron-Security, 2026).

Diese Standardwerte sind inzwischen gut, aber jeder davon ist ein Flag, das dein Code abschalten kann. Und weil jede App ihr eigenes Chromium mitbringt, bleibt ein Browser-Bug so lange in deiner installierten App, bis du ein Update auf Basis eines gepatchten Electron auslieferst.

Bei Wails fallen einige dieser Punkte durch das Design von vornherein weg. Es gibt kein Node.js in der Seite, also auch kein nodeIntegration, das du falsch konfigurieren könntest. Die Seite bekommt deine gebundenen Go-Methoden plus die Wails-Runtime-API und sonst nichts vom Host. Sie kann keine Dateien lesen und keine Prozesse starten, außer eine deiner Methoden tut das. Weil die Webview zum Betriebssystem gehört, kommen ihre Sicherheitsfixes über die sich selbst aktualisierende Evergreen WebView2 Runtime unter Windows, über macOS-Updates oder über die Pakete deiner Linux-Distribution, nicht über deine Release-Pipeline. Pinnst du unter Windows eine Fixed-Version-Runtime, liegt das Patchen wieder bei dir.

Ein Restrisiko bleibt. Jede gebundene Methode ist eine API, und die Seite, die sie aufruft, rendert vielleicht Inhalte, die du nicht kontrollierst. Im Log-Viewer oben akzeptiert TailLog jeden beliebigen Pfad. Zeigt deine App irgendwann nicht vertrauenswürdiges HTML an, lässt sich darüber jede beliebige Datei lesen. Validiere Argumente in Go genauso, wie du die Eingaben eines HTTP-Handlers validieren würdest: Beschränke Pfade auf erlaubte Verzeichnisse und URLs auf bekannte Hosts. Auch eine CSP ist weiterhin wichtig, denn die Seite kann wie jede Browserseite Netzwerk-Requests absetzen.

Zur verwandten Frage, was eine Node-Dependency schon bei der Installation anrichten kann, lies Ist Go besser vor Supply-Chain-Angriffen geschützt als Node.js?.

Wo kostet dich Wails etwas?

Wails tauscht einen mitgelieferten Browser gegen drei verschiedene Webviews, und das hat seinen Preis. Microsoft weist darauf hin, dass du mit der Evergreen WebView2 Runtime Tests auf Vorwärtskompatibilität einrichten solltest, weil sich die Engine unter deiner App ohne dein Zutun aktualisiert (Microsoft Learn, 2026). Unter macOS zielst du auf WebKit, die Engine hinter Safari. Teste dort also jedes CSS-Feature und jede Web-API, die du bisher nur in Chrome geprüft hast.

Linux ist die holprigste Plattform. Der Linux-Guide von Wails listet bekannte Probleme auf: Das Video-Event ended feuert wegen eines WebKitGTK-Bugs nicht, du siehst eventuell "GStreamer element autoaudiosink not found", und „WebKit installiert Signal-Handler, die Gos Mechanismus zur Panic-Recovery stören“ (Wails-Linux-Guide, 2026). Dazu kommt eine ABI-Spaltung. Debian 11, Ubuntu 20.04 und RHEL 8 bis 9 brauchen das ältere WebKitGTK 4.0, also wählst du zwischen den Build-Tags webkit2_41 und webkit2_40 (Wails-Distro-Support, 2026). Ein v3-Issue vom Februar 2026 meldet ein leeres Fenster unter X11 mit Nvidia, als Workaround dient WEBKIT_DISABLE_DMABUF_RENDERER=1 (Wails-Issue #4985, 2026).

Weitere Kosten, die du kennen solltest:

  • v2 kann nur ein Fenster. Laut v3-Migrationsguide „unterstützte v2 nur ein einziges Fenster pro Anwendung“, während v3 „native Multi-Window-Unterstützung als Kernfeature einführt“ (Wails-Guide von v2 zu v3, 2026).
  • v3 ist noch Beta. Die neueste Version ist v3.0.0-beta.25 vom 22. September 2026. In den Release Notes steht: „Die API ist stabil, aber vor dem finalen 3.0-Release können dir noch Probleme begegnen“ (Wails-Releases, 2026). Der Migrationsguide ergänzt: „v2 bleibt das aktuelle stabile Release.“
  • Das Ökosystem ist kleiner. Es gibt weniger Plugins, und wenn du auf einen seltsamen Bug stößt, ist die Chance kleiner, dass schon jemand den Fix aufgeschrieben hat.
  • Die Migrationsdoku ist dünn. Die Seite „from Electron“ in der v3-Doku ist aktuell nur ein Platzhalter.

Und was ist mit Tauri?

Tauri ist das andere große Webview-Framework. Es beschreibt sich als „ein Framework zum Bauen winziger, schneller Binaries für alle großen Desktop- und Mobile-Plattformen“, nutzt „die Webview, die auf dem System jedes Users bereits vorhanden ist“, und hat ein Rust-Backend (Tauri, 2026). Tauri 2.0 wurde am 2. Oktober 2024 stabil (Tauri-Blog, 2024).

Im Elanis-Benchmark lieferte Tauri die kleinsten Builds (etwa 3 bis 5 MB) und brauchte unter Linux den wenigsten Speicher. Gleichzeitig hatte es auf jedem Betriebssystem die langsamste Startzeit, auf dem Linux-CI-Runner sogar rund 30 Sekunden. Tauri und Wails haben dieselben Webview-Kompromisse, die Entscheidung hängt also vor allem an der Backend-Sprache. Schreibt dein Team Rust, nimm Tauri. Schreibt dein Team Go, nimm Wails.

Wie migrierst du eine Electron-App zu Wails?

Behalte dein Frontend und ersetze den Hauptprozess. Wails hat noch keinen offiziellen Migrationsguide für Electron. Plane die Arbeit deshalb, indem du jedes Electron-Teil seinem Go-Gegenstück zuordnest:

ElectronWails (Go)
ipcMain.handle + ipcRenderer.invoke über PreloadExportierte Methode auf einem gebundenen Struct, aufgerufen über generierte Bindings
fsos, io, bufio, path/filepath
child_processos/exec
fetch / axios im Hauptprozessnet/http mit einem Context-Timeout
webContents.send + ipcRenderer.onruntime.EventsEmit + EventsOn
electron-builderwails build, mit -nsis für einen Windows-Installer

Eine praktikable Reihenfolge:

  1. Übernimm das Frontend unverändert. Richte Wails auf den Output deines bestehenden Vite- oder webpack-Builds aus. Die meisten Komponenten müssen sich nicht ändern. Anpassen musst du nur die Stellen, die mit der Preload-API sprechen. Um die kümmert sich Schritt 2.
  2. Portiere einen IPC-Channel nach dem anderen. Aus jedem ipcMain.handle wird eine Go-Methode. Lösch den passenden Preload-Eintrag und stell die Aufrufstelle auf den generierten Import um.
  3. Ersetze Push-Nachrichten durch Events. Alles, was mit webContents.send verschickt wird, wird zu runtime.EventsEmit.
  4. Bau dein Packaging neu auf. wails build kompiliert „ein produktionsreifes Binary“, und Flags wie -nsis, -webview2 und -platform decken Installer, WebView2-Strategie und Cross-Targets ab (Wails-CLI, 2026). Der Signing-Guide behandelt die macOS-Notarisierung und Windows SignTool, inklusive GitHub Actions.
  5. Teste auf allen drei Webviews. Diesen Schritt gab es mit Electron nicht, plane also Zeit dafür ein.

Das Go, das du in Schritt 2 schreibst, ist größtenteils Code aus der Standardbibliothek. Wenn os, net/http und encoding/json neu für dich sind, decken der HTTP-Kurs und der Kurs zu Datenformaten die Teile ab, die ein Desktop-Backend nutzt.

Wo LevelUpGo ins Spiel kommt

Der Log-Viewer oben stützt sich auf Go-Grundlagen: Funktionen, mehrere Rückgabewerte, Fehlerbehandlung und die Standardbibliothek. Der Kurs Go Basics auf LevelUpGo bringt sie dir mit einem echten Editor neben jeder Lektion bei, und dein Code muss die Tests bestehen, bevor du weitermachst. Die Arbeit mit goroutines und context in FollowLog behandelt Concurrency Fundamentals. Wenn du mehr Wiederholungen willst, findest du im Training Ground eigenständige Übungen.

Wenn du noch überlegst, ob sich Go für dich lohnt, fang mit Lohnt es sich, 2026 Go zu lernen? an. Wo Go bereits in Produktion läuft, zeigt Wofür wird Go verwendet?, und für die Serverseite lies Beste Programmiersprache für Backend-Entwicklung 2026.

Häufig gestellte Fragen

Ist Wails besser als Electron?

Für die meisten kleinen und mittelgroßen Desktop-Apps ja. Im Elanis-Benchmark war eine leere Wails-App 30- bis 40-mal kleiner als eine Electron-App (Elanis-Benchmark, 2026), und du bekommst ein Go-Backend mit typisierten Bindings. Electron ist weiterhin besser, wenn du identisches Chromium-Rendering oder native Node-Module brauchst.

Braucht Wails weniger Speicher als Electron?

Das hängt vom Betriebssystem ab. Im selben Benchmark brauchte Wails unter macOS etwa 100 MB gegenüber 369 MB bei Electron und unter Linux 360 MB gegenüber 586 MB. Unter Windows brauchte es mehr, etwa 323 MB gegenüber 278 MB. Wahrscheinlich liegt das daran, dass WebView2 die Chromium-basierte Engine von Microsoft Edge nutzt und eigene Browser-Prozesse startet.

Ist Wails bereit für die Produktion?

Wails v2 ist das stabile Release, v2.14.0 erschien am 10. August 2026 (Wails-Releases, 2026). Apps wie Tiny RDM laufen darauf. Wails v3 ist in der Beta. Laut Doku laufen damit bereits Anwendungen in Produktion, sie rät aber dazu, vor dem Deployment gründlich zu testen.

Laufen Wails-Apps unter Windows 10?

Ja, solange die WebView2 Runtime installiert ist. Laut Microsoft ist sie auf der überwiegenden Mehrheit der Windows-10-Geräte bereits vorhanden (Microsoft Learn, 2026). Für den Rest kann Wails über das Build-Flag -webview2 einen Bootstrapper einbetten oder die Runtime bei der Installation herunterladen.

Kann ich mein React-Frontend beim Umstieg auf Wails behalten?

Ja. Wails liefert jedes gebaute Web-Frontend aus Dateien aus, die im Go-Binary eingebettet sind. React, Vue, Svelte und schlichtes HTML funktionieren also alle. Was sich ändert, ist die Kommunikation zwischen Frontend und Backend. IPC-Aufrufe werden zu Imports generierter Funktionen, und Push-Nachrichten werden zu Runtime-Events.

Quellen

Schreib Go wie ein Senior Engineer

Interaktive Lektionen im Browser. Die ersten sind kostenlos.

Kostenlose Lektion testenOder kostenloses Konto erstellen