參與貢獻

編輯此文件

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

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

部落格

邁向 Wails v3 之路

Wails 的版本資訊與公告

leaanthony閱讀時間 2 分鐘

多視窗螢幕截圖

簡介

Wails 是一個簡化使用 Go 編寫跨平台桌面應用程式的專案。它的前端使用原生 webview 元件(而非嵌入式瀏覽器),將全球最受歡迎的 UI 系統之強大能力帶入 Go,同時保持輕量。

2版本於2022年9月22日發布,帶來許多改進,包括:

  • 運用熱門的 Vite 專案進行即時開發
  • 用於管理視窗及建立選單的豐富功能
  • Microsoft 的 WebView2 元件
  • 產生與 Go 結構相對應的 TypeScript 模型
  • 建立 NSIS 安裝程式
  • 混淆建置

目前,Wails v2 提供了強大的工具,可用來建立功能豐富的跨平台桌面應用程式。

這篇部落格文章旨在探討專案目前的進展,以及未來有哪些可改進之處。

目前進展如何?

自 v2 發布以來,Wails 的普及程度持續提升,令人振奮。社群的創意及運用它打造出的精彩成果,總是不斷令我驚豔。隨著知名度提升,關注專案的人也變多了,功能要求和錯誤回報也隨之增加。

隨著時間推移,我已找出這個專案目前面臨的一些最迫切問題,也找出了一些阻礙專案發展的因素。

目前的問題

我認為以下幾個方面正在阻礙專案發展:

  • API
  • 繫結產生
  • 建置系統

API

目前,用於建置 Wails 應用程式的 API 由 2 個部分組成:

  • Application API
  • Runtime API

眾所周知,Application API 只有 1 個函式:Run()。它接受大量選項,用以控制應用程式的運作方式。雖然使用起來非常簡單,但限制也很大。這是一種「宣告式」方法,隱藏了許多底層複雜性。例如,它沒有主視窗的控制代碼,因此無法直接與主視窗互動;若要這麼做,就必須使用 Runtime API。當你開始想執行建立多個視窗之類較複雜的操作時,這就會成為問題。

Runtime API 為開發人員提供許多公用函式,包括:

  • 視窗管理
  • 對話方塊
  • 選單
  • 事件
  • 記錄

Runtime API 有幾個地方讓我不太滿意。首先,它要求到處傳遞「context」。這不僅令人困擾,也會讓傳入 context 後卻遇到執行階段錯誤的新手開發人員感到困惑。

Runtime API 最大的問題是,它原本是為僅使用單一視窗的應用程式而設計。隨著時間推移,對多視窗的需求日益增加,而這套 API 並不適合這種用途。

對 v3 API 的構想

如果能像這樣做,不是很棒嗎?

go
func main() {
    app := wails.NewApplication(options.App{})
    myWindow := app.NewWindow(options.Window{})
    myWindow.SetTitle("My Window")
    myWindow.On(events.Window.Close, func() {
        app.Quit()
    })
    app.Run()
}

這種程式化方法直覺得多,並讓開發人員能直接與應用程式元素互動。目前所有用於視窗的 runtime 方法都可以直接成為視窗物件的方法。至於其他 runtime 方法,則可以像這樣移到應用程式物件:

go
app := wails.NewApplication(options.App{})
app.NewInfoDialog(options.InfoDialog{})
app.Log.Info("Hello World")

這是一套強大得多的 API,可用來建置更複雜的應用程式。它也能建立多個視窗,而這是GitHub 上獲得最多贊成票的功能:

go
func main() {
    app := wails.NewApplication(options.App{})
    myWindow := app.NewWindow(options.Window{})
    myWindow.SetTitle("My Window")
    myWindow.On(events.Window.Close, func() {
        app.Quit()
    })
    myWindow2 := app.NewWindow(options.Window{})
    myWindow2.SetTitle("My Window 2")
    myWindow2.On(events.Window.Close, func() {
        app.Quit()
    })
    app.Run()
}

繫結產生

Wails 的主要功能之一,是為 Go 方法產生繫結,讓你能從 JavaScript 呼叫這些方法。目前的做法有點像權宜之計:先使用特殊旗標建置應用程式,再執行產生的二進位檔;該二進位檔會利用反射判斷繫結了哪些項目。這造成了類似先有雞還是先有蛋的困境:沒有繫結就無法建置應用程式,而不建置應用程式就無法產生繫結。這個問題有許多規避方式,但最好的做法是完全不要採用這種方法。

我們曾多次嘗試為 Wails 專案編寫靜態分析器,但都沒有太大進展。近來,隨著這方面可用的資料增加,實作起來已稍微容易一些。

與反射相比,AST 方法快得多,但也複雜得多。一開始,我們可能需要對如何在程式碼中指定繫結施加某些限制。目標是先支援最常見的使用案例,之後再加以擴充。

建置系統

與 API 的宣告式方法一樣,建置系統的設計目的也是隱藏建置桌面應用程式的複雜性。執行 wails build 時,它會在背後執行許多工作:

  • 建置用於繫結的後端二進位檔並產生繫結

  • 安裝前端相依套件

  • 建置前端資產

  • 判斷是否有應用程式圖示,若有則將其嵌入

  • 建置最終二進位檔

  • 如果建置目標是 darwin/universal,便會建置 2 個二進位檔,一個用於 darwin/amd64,另一個用於 darwin/arm64,再使用 lipo 建立通用二進位檔

  • 如果需要壓縮,則使用 UPX 壓縮二進位檔

  • 判斷是否要封裝此二進位檔;若要封裝,則:

    • 確保圖示和應用程式資訊清單已編譯至二進位檔中(Windows)
    • 建置應用程式套件、產生並複製圖示套件,並將二進位檔和 Info.plist 複製到應用程式套件中(Mac)
  • 如果需要 NSIS 安裝程式,則進行建置

這整個流程雖然功能非常強大,卻也非常不透明。它很難自訂,也很難偵錯。

為了解決 v3 中的這個問題,我希望改用存在於 Wails 外部的建置系統。使用 Task 一段時間後,我非常喜歡它。它是設定建置系統的絕佳工具,任何使用過 Makefile 的人應該都會覺得相當熟悉。

建置系統將使用 Taskfile.yml 檔案進行設定;任何受支援的範本都會預設產生此檔案。它將包含執行目前所有工作所需的步驟,例如建置應用程式或將其封裝,讓自訂變得更容易。

這項工具不需要任何外部相依項目,因為它將成為 Wails CLI 的一部分。這表示你仍然可以使用 wails build,而它會完成目前所做的一切。不過,如果你想自訂建置流程,可以編輯 Taskfile.yml 檔案。這也表示你可以輕鬆了解建置步驟,並視需要使用自己的建置系統。

建置流程中還缺少一塊拼圖:圖示產生、壓縮和封裝等不可再分的作業。如果要求開發人員安裝一堆外部工具,使用體驗不會很好。為了解決這個問題,Wails CLI 將在 CLI 中提供所有這些功能。這表示不需要額外的外部工具,建置仍會如預期運作;但你也可以使用任何喜歡的工具取代建置流程中的任何步驟。

這將是一套透明得多的建置系統,不僅更容易自訂,也能解決許多相關的既有問題。

成果

這些正向變革將為專案帶來巨大的效益:

  • 新的 API 將直覺得多,並能用來建置更複雜的應用程式。
  • 使用靜態分析產生繫結將快得多,並能大幅降低目前流程的複雜度。
  • 使用成熟的外部建置系統將使建置流程完全透明,並提供強大的自訂能力。

專案維護者將獲得以下效益:

  • 新的 API 將更容易維護,也更容易因應新功能和新平台進行調整。
  • 新的建置系統將更容易維護和擴充。我希望這能催生由社群推動的全新建置管線生態系。
  • 專案內部的關注點將獲得更妥善的分離,讓新增功能和平台變得更容易。

計畫

這方面的許多實驗工作都已經完成,而且成果看起來不錯。目前這項工作還沒有明確時程,但我希望能在 2023 第一季結束前推出 Mac Alpha 版本,讓社群測試、實驗並提供意見回饋。

總結

  • v2 API 採宣告式設計,對開發人員隱藏了許多細節,也不適合多視窗等功能。我們將建立一套更簡潔、更直覺且功能更強大的新 API。
  • 目前的建置系統不透明且難以自訂,因此我們將改用外部建置系統,讓整個流程全面開放。
  • 目前的繫結產生流程緩慢且複雜,因此我們將改用靜態分析,以消除現行方法中的許多複雜性。

我們已經為 v2 的核心投入大量心力,目前它相當穩固。現在該著手改善其上層,為開發人員提供好得多的使用體驗。

希望你和我一樣對此感到興奮。我很期待聽到你的想法和意見回饋。

敬上,

‐ Lea

附註:如果你或你的公司認為 Wails 很實用,請考慮贊助本專案。謝謝!

再附註:沒錯,那確實是使用 Wails 建置的多視窗應用程式螢幕截圖,不是示意圖。它是真的。它棒極了。即將推出。