參與貢獻

編輯此文件

翻譯文件,或在您的電腦上開啟完整專案。

在您選擇提交成果之前,不會發布任何內容。

Wails 的運作方式

瞭解 Wails 架構及其如何實現原生效能

Wails 是一個桌面應用程式開發框架,使用Go 建構後端,並使用網頁技術建構前端。但與 Electron 不同,Wails 不會內附瀏覽器,而是使用作業系統的原生 WebView。

Wails 應用程式, 前端, Go 後端, 作業系統, 初始化, 提供靜態 Web 應用程式, 透過作業系統原生 WebView 呈現網站, 一般通訊, 發出 API 形式的呼叫, 服務處理要求, 產生回應, 處理回應

與 Electron 的主要差異:

面向 Wails Electron
瀏覽器 作業系統提供的 WebView 內附 Chromium(約 100MB)
後端 Go(編譯執行) Node.js(直譯執行)
通訊 記憶體內橋接器 IPC(處理程序間通訊)
套件大小 約 15MB 約 150MB
記憶體 約 10MB 約 100MB 以上
啟動時間 <0.5 秒 2-3 秒

核心元件

1. 原生 WebView

Wails 使用作業系統內建的網頁轉譯引擎:

WebView2(Microsoft Edge WebView2)

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

這一點為何重要:

  • 不內附瀏覽器 → 應用程式更小
  • 作業系統原生 → 整合度與效能更佳
  • 自動更新 → 透過作業系統更新取得安全性修補程式
  • 熟悉的轉譯結果 → 與系統瀏覽器相同

2. Wails 橋接器

橋接器是 Wails 的核心,可讓 Go 與 JavaScript 之間進行直接通訊。

前端(JavaScript), Wails 橋接器, JSON 編碼器, 方法路由器, JSON 解碼器, 後端(Go), 已註冊的服務

運作方式:

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

效能特性:

  • 記憶體內通訊:沒有網路額外負擔,也不使用 HTTP
  • 盡可能採用零複製(適用於大型資料)
  • 預設為非同步:兩端皆不會阻塞
  • 型別安全:自動產生 TypeScript 定義

3. 服務系統

建議透過服務將 Go 功能公開給前端。

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 會在啟動時掃描您的 struct
  • 匯出的方法可供前端呼叫
  • 系統會擷取型別資訊,用於 TypeScript 繫結
  • 錯誤處理會自動進行(Go 錯誤 → JS 例外)

產生的 TypeScript 繫結:

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

為何使用服務?

  • 型別安全:完整支援 TypeScript
  • 自動探索:無須手動註冊方法
  • 條理分明:將相關功能分組
  • 可測試:服務只是 Go 結構體

深入瞭解服務 →

4. 事件系統

事件讓元件之間能透過發布/訂閱模式進行通訊。

Wails 事件系統, 視窗 1, 視窗 2, Go 後端, 事件驅動器, 訂閱 'data-updated' 事件, 訂閱 'data-updated' 事件, 應用程式 Emit('data-updated', data), 訂閱者透過 On('data-updated', handler) 處理, 訂閱者透過 On('data-updated', handler) 處理

使用情境:

  • 視窗通訊:一個視窗通知其他視窗
  • 背景工作:Go 服務向 UI 通知進度
  • 狀態同步:讓多個視窗保持同步
  • 鬆散耦合:元件不需要直接參照彼此

範例:

go
// Go: Emit an event
app.Event.Emit("user-logged-in", user)
javascript
// JavaScript: Listen for event
import { Events } from '@wailsio/runtime'

Events.On('user-logged-in', (user) => {
    console.log('User logged in:', user)
})

深入瞭解事件 →

應用程式生命週期

瞭解生命週期有助於掌握初始化資源及執行清理的時機。

應用程式啟動, 初始化, 建立應用程式, 註冊服務, 設定視窗/選單, 事件迴圈, 處理事件, 處理訊息, 更新使用者介面, 關閉, 清理資源, 儲存狀態, 應用程式結束

生命週期掛鉤:

go
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上沒有OnStartup欄位。啟動工作應放在服務的ServiceStartup(ctx, options)中、透過app.Event.OnApplicationEvent(events.Common.ApplicationStarted, ...)註冊的回呼中,或直接放在app.Run()之前。

深入瞭解生命週期 →

建置流程

瞭解 Wails 如何建置應用程式:

原始碼, Go 程式碼 (main.go, 服務), 前端程式碼 (HTML/CSS/JS), 建置流程, 分析 Go 程式碼, 產生繫結, 建置前端, 編譯 Go, 嵌入資產, 輸出, 原生二進位檔 (myapp.exe/.app)

建置步驟:

  1. 分析 Go 程式碼
  • 掃描服務中的匯出方法
  • 擷取參數與傳回型別
  • 產生方法簽章
  1. 產生 TypeScript 繫結
  • 為每個服務建立.ts檔案
  • 包含完整的型別定義
  • 新增 JSDoc 註解
  1. 建置前端
  • 執行打包工具(Vite、webpack 等)
  • 縮小並最佳化
  • 輸出至frontend/dist/
  1. 編譯 Go
  • 啟用最佳化進行編譯(-ldflags="-s -w")
  • 包含建置中繼資料
  • 針對特定平台進行編譯
  1. 嵌入資產
  • 將前端檔案嵌入 Go 二進位檔
  • 壓縮資產
  • 建立單一可執行檔

結果:所有內容均已嵌入的單一原生可執行檔。

深入瞭解建置 →

開發環境與正式環境

Wails 在開發環境與正式環境中的行為有所不同:

特性:

  • 熱重載:前端變更會立即重新載入
  • 原始碼對應表:使用原始程式碼進行偵錯
  • DevTools:可使用瀏覽器 DevTools
  • 記錄:啟用詳細記錄
  • 外部前端:由開發伺服器(Vite)提供

運作方式:

Wails 應用程式, Vite 開發伺服器 (localhost:5173), WebView

優點:

  • 立即取得變更回饋
  • 完整的偵錯功能
  • 加快反覆開發速度

記憶體模型

瞭解記憶體使用情況,有助於建置高效率的應用程式。

記憶體區域:

  1. Go 堆積
  • 您的服務與應用程式狀態
  • 由 Go 垃圾回收器管理
  • 簡易應用程式通常為 5-10MB
  1. WebView 記憶體
  • DOM、JavaScript 堆積、CSS
  • 由 WebView 引擎管理
  • 簡易應用程式通常為 10-20MB
  1. 橋接層記憶體
  • 用於通訊的訊息緩衝區
  • 額外負擔極低(<1MB)
  • 大型資料會盡可能採用零複製

最佳化提示:

  • 避免傳輸大量資料:傳遞 ID,並視需要擷取詳細資料
  • 使用事件進行更新:不要從前端輪詢
  • 以串流方式處理大型檔案:不要將整個檔案載入記憶體
  • 清除監聽器:使用完畢後移除事件監聽器

深入瞭解效能 →

安全性模型

Wails 提供預設安全的架構:

前端(不受信任), Wails 橋接器(驗證), 後端(受信任)

安全性功能:

  1. 方法白名單
  • 只能呼叫匯出的方法
  • 無法存取私有方法
  • 必須明確註冊服務
  1. 型別驗證
  • 依據 Go 型別檢查引數
  • 拒絕無效的型別
  • 防止注入攻擊
  1. 不使用 eval()
  • 前端無法執行任意 Go 程式碼
  • 只能呼叫預先定義的方法
  • 不會動態執行程式碼
  1. 情境隔離
  • 每個視窗都有自己的情境
  • 服務可以檢查呼叫端的情境
  • 可為每個視窗設定不同權限

最佳實務:

  • 在 Go 中驗證使用者輸入(不要信任前端)
  • 使用情境進行驗證與授權
  • 執行檔案操作前,先清理檔案路徑
  • 對高成本操作實施速率限制

深入瞭解安全性 →

後續步驟

應用程式生命週期 - 瞭解啟動、關閉及生命週期掛鉤 深入瞭解 →

Go 與前端的橋接層 - 深入探討橋接層的運作方式 深入瞭解 →

建置系統 - 瞭解 Wails 如何建置您的應用程式 深入瞭解 →

開始建置 - 透過教學實作所學內容 教學 →


對架構有疑問嗎?請在Discord中提問,或查閱API 參考。

編輯頁面

上次更新: