Aller au contenu

Comment fonctionne Wails

Wails est un framework pour créer des applications de bureau en utilisant Go pour le backend et les technologies web pour le frontend. Mais contrairement à Electron, Wails n’inclut pas de navigateur ; il utilise le WebView natif du système d’exploitation.

Diagram

Différences clés par rapport à Electron :

AspectWailsElectron
NavigateurWebView fourni par le OSChromium intégré (~100 Mo)
BackendGo (compilé)Node.js (interprété)
CommunicationPont en mémoireIPC (inter-processus)
Taille du bundle~15 Mo~150 Mo
Mémoire~10 Mo~100 Mo+
Démarrage<0,5 s2-3 s

Wails utilise le moteur de rendu web intégré au système d’exploitation :

WebView2 (Microsoft Edge WebView2)

  • Basé sur Chromium (identique au navigateur Edge)
  • Préinstallé sur Windows 10/11
  • Mises à jour automatiques via Windows Update
  • Prise en charge complète des normes web modernes

Pourquoi cela compte :

  • Pas de navigateur intégré → Taille d’application réduite
  • Natif au système → Meilleure intégration et performances
  • Mises à jour automatiques correctifs de sécurité via les mises à jour du système
  • Rendu familier → Identique au navigateur du système

Le pont est le cœur de Wails ; il permet une communication directe entre Go et JavaScript.

Diagram

Fonctionnement :

  1. Le frontend appelle une méthode Go (via le binding auto-généré)
  2. Le pont encode l’appel en JSON (nom de la méthode + arguments)
  3. Le routeur trouve la méthode Go dans les services enregistrés
  4. La méthode Go s’exécute et retourne une valeur
  5. Le pont décode le résultat et l’envoie au frontend
  6. La Promise se résout en JavaScript avec le résultat

Caractéristiques de performance :

  • En mémoire : Pas de surcharge réseau, pas de HTTP
  • Zero-copy lorsque cela est possible (pour les gros volumes de données)
  • Asynchrone par défaut : Non-bloquant des deux côtés
  • Typé de manière sûre : Définitions TypeScript auto-générées

Les services sont la méthode recommandée pour exposer la fonctionnalité Go au frontend.

// 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, "}),
},
})

Découverte des services :

  • Wails analyse votre struct au démarrage
  • Les méthodes exportées deviennent appelables depuis le frontend
  • Les informations de type sont extraites pour les bindings TypeScript
  • La gestion des erreurs est automatique (erreurs Go → exceptions JS)

Binding TypeScript généré :

// Auto-generated in frontend/bindings/GreetService.ts
export function Greet(name: string): Promise<string>
export function GetTime(): Promise<Date>

Pourquoi utiliser des services ?

  • Typé de manière sûre : Prise en charge complète de TypeScript
  • Découverte automatique : Pas d’enregistrement manuel des méthodes
  • Organisé : Regroupez les fonctionnalités liées
  • Testable : Les services sont de simples structs Go

En savoir plus sur les services →

Les événements permettent une communication pub/sub entre les composants.

Diagram

Cas d’utilisation :

  • Communication entre fenêtres : Une fenêtre notifie les autres
  • Tâches en arrière-plan : Le service Go notifie l’UI de la progression
  • Synchronisation d’état : Garder plusieurs fenêtres synchronisées
  • Découplage lâche : Les composants n’ont pas besoin de références directes

Exemple :

// 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)
})

En savoir plus sur les événements →

Comprendre le cycle de vie vous aide à savoir quand initialiser les ressources et les nettoyer.

Diagram

Lifecycle hooks:

app := application.New(application.Options{
Name: "My App",
// Called before windows are created
OnStartup: func(ctx context.Context) {
// Initialise database, load config, etc.
},
// Called when app is about to quit
OnShutdown: func() {
// Save state, close connections, etc.
},
})

Learn more about lifecycle →

Understanding how Wails builds your application:

Diagram

Build steps:

  1. Analyse Go code

    • Scan services for exported methods
    • Extract parameter and return types
    • Generate method signatures
  2. Generate TypeScript bindings

    • Create .ts files for each service
    • Include full type definitions
    • Add JSDoc comments
  3. Build frontend

    • Run your bundler (Vite, webpack, etc.)
    • Minify and optimise
    • Output to frontend/dist/
  4. Compile Go

    • Compile with optimisations (-ldflags="-s -w")
    • Include build metadata
    • Platform-specific compilation
  5. Embed assets

    • Embed frontend files into Go binary
    • Compress assets
    • Create single executable

Result: A single native executable with everything embedded.

Learn more about building →

Wails behaves differently in development and production:

Characteristics:

  • Hot reload: Frontend changes reload instantly
  • Source maps: Debug with original source
  • DevTools: Browser DevTools available
  • Logging: Verbose logging enabled
  • External frontend: Served from dev server (Vite)

How it works:

Diagram

Benefits:

  • Instant feedback on changes
  • Full debugging capabilities
  • Faster iteration

Understanding memory usage helps you build efficient applications.

Memory regions:

  1. Go Heap

    • Your services and application state
    • Managed by Go garbage collector
    • Typically 5-10MB for simple apps
  2. WebView Memory

    • DOM, JavaScript heap, CSS
    • Managed by WebView’s engine
    • Typically 10-20MB for simple apps
  3. Bridge Memory

    • Message buffers for communication
    • Minimal overhead (<1MB)
    • Zero-copy for large data where possible

Optimisation tips:

  • Avoid large data transfers: Pass IDs, fetch details on demand
  • Use events for updates: Don’t poll from frontend
  • Stream large files: Don’t load entirely into memory
  • Clean up listeners: Remove event listeners when done

Learn more about performance →

Wails provides a secure-by-default architecture:

Diagram

Security features:

  1. Method whitelisting

    • Only exported methods are callable
    • Private methods are inaccessible
    • Explicit service registration required
  2. Type validation

    • Arguments checked against Go types
    • Invalid types rejected
    • Prevents injection attacks
  3. No eval()

    • Frontend can’t execute arbitrary Go code
    • Only predefined methods callable
    • No dynamic code execution
  4. Context isolation

    • Each window has its own context
    • Services can check caller context
    • Permissions per window possible

Best practices:

  • Validate user input in Go (don’t trust frontend)
  • Use context for authentication/authorisation
  • Sanitise file paths before file operations
  • Rate limit expensive operations

Learn more about security →

Application Lifecycle - Understand startup, shutdown, and lifecycle hooks
Learn More →

Go-Frontend Bridge - Deep dive into how the bridge works
Learn More →

Build System - Understand how Wails builds your application
Learn More →

Start Building - Apply what you’ve learned in a tutorial Tutorials →


Des questions sur l’architecture ? Posez-les sur Discord ou consultez la référence de l’API.