初試 Tauri - 移植 ASP.NET Core 桌面小工具範例
| | | 0 | |
對略懂前端的全端攻城獅來說,把網頁前端加 WebAPI 包成桌面程式,可省下學習摸索 WinForm/WPF 的時間,是絕佳的技能再利用典範。Electron 要包進整個 Chromium 導致程式高達數百 MB 太痴肥,不適合用來寫小工具。熟悉 ASP.NET Core 與 Vue 的我,幾年前想出將 ASP.NET Core 網站轉成單一檔案 exe 寫桌面小工具的點子,執行時叫出內建瀏覽器當 UI,網頁關閉時自動結束程式,在標準 ASP.NET Core Minimal API 專案引用 NuGet Package,改幾行程式便能華麗變身為桌面小工具,體積可低到幾 MB,成效讓我非常滿意。Electron.NET 太笨重?用 ASP.NET Core Minimal API 寫桌面小工具的快速做法
時間來到 2026,以 Rust 作為後端的 Tauri 框架漸成寫桌面程式的流行做法。Tauri 後端使用 Rust,前端可沿用 HTML、CSS、JavaScript,透過作業系統內建的 WebView 呈現 UI,不像 Electron 必須包進 Chromium 而過胖。加上靠著 Rust 語言特性,能做到執行檔僅數 MB 至數十 MB,執行效率極高記憶體用量又低,攻擊面小且高度記憶體安全,並能支援 iOS/Android 跨平台。唯一的缺點大概是 Rust 是門艱澀難學的程式語言,非凡夫俗子可輕鬆駕御。Tauri 早在 2022 年就發佈 1.0 版,必須要會 Rust 成為阻擋凡人接近的高聳城牆;直到 Vibe Coding 時代來臨,「人不一定要會程式語言,AI 會就好」讓 Rust 門檻瞬間消失,只要 AI 在手,人人都能用 Tauri,於是用 Tauri 開發的程式開始多了起來。
我的立場偏保守,評估開發方式時還是想保留人工介入的後路,從這個角度出發,桌面小工具要嘛續用 .NET 為基礎的做法,要嘛認真學好 Rust 放心擁抱 Tauri。
在搞懂 Rust 之前,這篇會先體驗 Tauri 長什麼樣子,以上回文章的 AES 加解密工具當範例,看看若改用 Tauri 寫長什麼樣子,有具體參照物,更能快速理解 Tauri 的架構與運作原理。
開了 Github Copilot 請 Claude Opus 5.5 參考 ASP.NET Core 版本專案及我的部落格文章,翻寫出一個 Tauri 版本,耗時約半小時(含安裝套件),花費近 2 塊美金。與人工開發相比,這成本低到不可思議~

都用上 Opus 等級,毫無意外,一次搞定且功能正確。(說不定用 Sonnet 也成,AI 強成這樣,我該告老還鄉了...)
檔案僅 3MB,不需其他 dll 或附屬檔案,這是 Rust 的迷人之處。
專案結構如下:

hello-tauri/:專案根目錄.gitignore:排除src-tauri/target/與src-tauri/gen/schemas/等建置產物ui/:前端靜態檔,對應原專案的ui/資料夾;由tauri.conf.json的frontendDist指定,編譯時嵌入 exeindex.html:畫面版面,CSS 與 Vue 模板沿用原版;移除<form>、隱藏<iframe>及/sse.jsapp.js:Vue app 邏輯,以window.__TAURI__.core.invoke('aes', …)呼叫後端(原版的 inline script 移到這裡,以便 CSP 不需開'unsafe-inline')vue.global.prod.min.js:Vue 3 執行檔,直接從原專案複製
src-tauri/:Rust 後端與 Tauri 設定,對應原專案的Program.cs、AesEncryptor.csprojCargo.toml:套件名稱與相依套件(tauri、serde、aes、cbc、sha2、base64),以及 release 縮小體積的設定(LTO、opt-level = "s"、strip);相當於.csprojCargo.lock:鎖定所有相依套件的實際版本,確保每次建置結果一致;應納入版控(相當於packages.lock.json)build.rs:建置腳本,呼叫tauri_build::build(),負責讀取tauri.conf.json、把圖示與版本資訊寫入 Windows 資源、產生權限 schematauri.conf.json:Tauri 主設定檔,包含產品名稱/識別碼、前端目錄、withGlobalTauri、視窗標題與大小、CSP、打包格式及圖示清單app-icon.png:1024×1024 的圖示原始檔,用來產生icons/下各尺寸圖示(也可交給cargo tauri icon產生)capabilities/:Tauri 2 的權限設定default.json:授予main視窗core:default權限
icons/:程式圖示,由tauri.conf.json的bundle.icon引用icon.ico:Windows 執行檔與視窗圖示(內含 16~256 px 多種尺寸),Windows 建置必備32x32.png、128x128.png、[email protected]:Linux 等平台與安裝檔使用的 PNG 圖示
src/:Rust 原始碼main.rs:程式進入點;release 版隱藏主控台視窗,定義#[tauri::command] fn aes(對應MapPost("/aes")),建立 Tauri 應用程式並註冊 commandcrypto.rs:CodecNetFx的 Rust 版 AES-128-CBC 加解密,以及用 .NET 實算結果驗證相容性的單元測試
gen/schemas/:build.rs產生的 JSON schema(acl-manifests.json、capabilities.json、desktop-schema.json、windows-schema.json),讓編輯器能檢查capabilities/*.json的內容 (版控排除)target/:Cargo 建置輸出 (版控排除)debug/:cargo run/cargo test的產物(有主控台、可開 DevTools)release/:cargo build --release的產物,最終成品為release/aes-encryptor.exe(約 3.1 MB)
補充一些小心得:
cargo install tauri-cli比預期耗時,有 870 個套件要下載並編譯:

編譯過程可看到所有 CPU 一起衝上 100% 的盛況,總耗時約 10 分鐘:

- Tauri 有嚴格的權限控制 (畢竟要在 Android/iOS 跑,權限必須明確宣告),capabilities.json 讓 main 視窗可以使用 Tauri 核心的預設功能。若要使用檔案系統、對話框、shell 等外掛功能,需要在 permissions 中另外加入,例如 "fs:default"、"dialog:default"。
{ "default": { "identifier": "default", "description": "Permissions for the main window", "local": true, "windows": [ "main" ], "permissions": [ "core:default" ] } } - Tauri 雖然可以跑網頁,開啟網址為
http://tauri.localhost/(macOS/Linux 為tauri://localhost/),走 WebView 的自訂協定處理器,這類網址只在 WebView 中有效。
開發模式(tauri dev)時則是用 dev server,例如 Vite 的http://localhost:1420/(由 tauri.conf.json 的 build.devUrl 決定) 。這個網址就可以直接用瀏覽器打開,但瀏覽器中無法使用 Tauri 的 API (invoke 等) ,因為沒有 Tauri 的 IPC 橋接。 - 網頁與後端溝通,預設並不是透過 WebAPI 溝通,要改用 Tauri 提供的 invoke() 方法,例如:
後端寫法如下,其中const { invoke } = window.__TAURI__.core; // withGlobalTauri: true 才會注入 result = await invoke('aes', { mode, key: this.EncKey, data });#[tauri::command]是 Tauri 的屬性巨集 (Attribute Macro),用來把一個 Rust 函式標記成「可以被前端 JavaScript/TypeScript 呼叫的指令」:/// Equivalent of `app.MapPost("/aes", ...)` in the ASP.NET Core version. /// Called from JavaScript with `invoke('aes', { mode, key, data })`. #[tauri::command] fn aes(mode: String, key: String, data: String) -> Result<String, String> { if key.is_empty() || data.is_empty() { return Err("parameter missing".into()); } if mode == "decrypt" { crypto::aes_decrypt(&key, &data) } else { Ok(crypto::aes_encrypt(&key, &data)) } } - Rust 然是用
rustc編譯,但要產生 Windows 執行檔仍需由 linker (連結器) 將編譯結果與原生函式庫連結起來。Windows 上的 Rust 有兩種常見工具鏈:stable-x86_64-pc-windows-msvc:Microsoft 的 MSVC linker、Windows SDK 與相關函式庫,由 Visual Studio / Build Tools 提供 (與微軟原生元件整合,也是 Tauri 在 Windows 上的標準建置環境)stable-x86_64-pc-windows-gnu:MinGW-w64/GNU 工具與相關函式庫 可使用以下 CLI 檢查工具鏈
兩者都能編譯 Rust、產生 Windows exe,編譯 Windows 平台執行檔選擇 stable-x86_64-pc-windows-msvc 的好處在於 MSVC 是官方文件採用的工具鏈,較容易照文件建置、排除問題,可避開 MinGW 環境安裝設定問題。要使用 MSVC,開發環境需安裝 Build Tools for Visual Studio 2022。rustup toolchain list # 列出已安裝的工具鏈 rustup toolchain install stable-x86_64-pc-windows-msvc # 若沒有 MSVC 裝這個,但 C++ 編譯工具要先自己裝好 rustup show active-toolchain # 顯示目前目錄實際使用的工具鏈 (預設 GNU 版) cargo +stable-x86_64-pc-windows-msvc build # 指定本次使用 MSVC 版 - 編譯、測試、執行、發行
# 編譯 cargo +stable-x86_64-pc-windows-msvc build # 設定本專案用 MSVC,之後可免加 +stable-x86_64-pc-windows-msvc rustup override set stable-x86_64-pc-windows-msvc # 全機預設用 MSVC ustup default stable-x86_64-pc-windows-msvc # 單元測試(驗證與 .NET 版相容) cargo +stable-x86_64-pc-windows-msvc test # 開發執行(有主控台、可開 DevTools) cargo +stable-x86_64-pc-windows-msvc run # 正式版:產生 target\release\aes-encryptor.exe(約 3 MB,可直接複製使用) cargo +stable-x86_64-pc-windows-msvc build --release --features tauri/custom-protocol
實際了解 Tauri 的做法,會發現雖然 HTML / JavaScript 可以沿用,但原本的 fetch、GET/POST 等 AJAX 互動方式要修改,改走 invoke(),若希望網頁與 Tauri 共用一套,理想做法應該是先將網頁與後端互動全部收攏成少數介面或共用函式,再開發 Web 版及 Tauri 版,如此前端其他不用動,在不同情境抽換介面或共用函式即可在兩個平台順利運行。
體驗完畢~
Revisiting earlier ASP.NET Core approach to desktop tools and tries Tauri, a Rust-based framework that uses the OS’s built-in WebView instead of bundling Chromium. By having Claude Opus port an AES encryption tool to Tauri in about half an hour, the author gets a correct 3 MB executable. The post walks through the project structure, permissions, the invoke() bridge, MSVC toolchain setup, and build commands.
Comments
Be the first to post a comment