跳到內容

Wails 運作原理

Wails 是一個用於構建桌面應用程式的框架,採用 Go 作為後端Web 技術作為前端。但與 Electron 不同,Wails 並未捆綁瀏覽器,而是使用 作業系統的原生 WebView

Diagram

與 Electron 的主要差異:

面向WailsElectron
瀏覽器作業系統提供的 WebView捆綁 Chromium(約 100MB)
後端Go(編譯後)Node.js(解釋執行)
通訊記憶體橋接IPC(進程間通訊)
套件大小約 15MB約 150MB
記憶體佔用約 10MB約 100MB+
啟動速度<0.5 秒2-3 秒

Wails 使用作業系統內建的網頁渲染引擎:

WebView2(Microsoft Edge WebView2)

  • 基於 Chromium(與 Edge 瀏覽器相同)
  • 預裝於 Windows 10/11
  • 透過 Windows Update 自動更新
  • 完整支援現代網頁標準

這為什麼重要:

  • 無捆綁瀏覽器 → 應用程式體積更小
  • 作業系統原生 → 更好的整合與效能
  • 自動更新 → 從作業系統更新獲得安全修補
  • 熟悉的渲染 → 與系統瀏覽器相同

橋接器是 Wails 的核心——它實現了 Go 與 JavaScript 之間的直接通訊

Diagram

運作方式:

  1. 前端呼叫 Go 方法(透過自動產生的繫結)
  2. 橋接器將呼叫編碼為 JSON(方法名稱 + 參數)
  3. 路由器在已註冊的服務中找到 Go 方法
  4. Go 方法執行並返回值
  5. 橋接器解碼結果並傳回前端
  6. JavaScript 中的 Promise 解析並獲得結果

效能特性:

  • 記憶體內:無網路開銷,無 HTTP
  • 零複製(在可能的情况下,針對大量資料)
  • 預設非同步:兩側均非阻塞
  • 型別安全:自動產生 TypeScript 定義

服務是向後端暴露 Go 功能的推薦方式。

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

服務發現:

  • Wails 在啟動時掃描您的結構體
  • 公開方法可從前端呼叫
  • 型別資訊被提取用於 TypeScript 繫結
  • 錯誤處理是自動的(Go 錯誤 → JS 異常)

產生的 TypeScript 繫結:

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

為什麼使用服務?

  • 型別安全:完整的 TypeScript 支援
  • 自動發現:無需手動註冊方法
  • 組織良好:分組相關功能
  • 可測試:服務只是 Go 結構體

了解更多關於服務 →

事件實現元件之間的發布/訂閱通訊

Diagram

使用情境:

  • 視窗通訊:一個視窗通知其他視窗
  • 背景任務:Go 服務通知 UI 進度
  • 狀態同步:保持多個視窗同步
  • 鬆耦合:元件不需要直接參考

範例:

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

了解更多關於事件 →

了解生命週期可幫助您知道何時初始化資源和清理。

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 →


對架構有疑問? 請在 Discord 提問或查看 API 參考文件