Tauri:將Javascript與Rust結合構建GUI桌面應用
我們重新審視 Tauri,這是一個使用任何前端框架和 Rust 核心構建桌面應用程序的框架。我們查看了 2.0 beta 版。
譯自Tauri: Mixing JavaScript With Rust for GUI Desktop Apps,作者 David Eastman。
在我 2022 年 1 月對 Tauri 的首次評論中,我指出它是一個框架,可以使用任何前端框架和 Rust 內核構建桌面應用程序。由于 Rust 語言在過去兩年半的時間里在流行度方面取得了顯著進步,我認為再次回顧 Tauri 是值得的——尤其是因為它最近發布了 2.0 版本。
Tauri 的宣傳語是“構建一個針對多平臺部署的優化、安全且與前端無關的應用程序”,這與之前的說法一致,但更多的部署目標使其更符合我最近發布的其他產品。額外的好處是,可以使用熟悉的 Web 方法構建桌面和移動應用程序。
我們獲得了 Rust 的安全性,但也獲得了 Web 開發的熟悉性和靈活性。
我們將嘗試看看構建一個可以在我的 Mac 上完全打包運行的 UI 應用程序的路徑是否變得更加平滑。Tauri 仍然將自己稱為一個“工具包”,這仍然是事實。
從概念上講,Tauri 充當一個靜態 Web 主機。因此,Tauri 與 Rust 框架和系統的原生 Web 視圖協同工作,以輸出一個體積適中的可執行應用程序。理論上,我們獲得了 Rust 的安全性,但也獲得了 Web 開發的熟悉性和靈活性。
入門路線看起來更新了一些,現在流行的是單行啟動。在我們開始之前,我懷疑我有一個舊的 Rust 安裝,所以我應該更新它。使用先決條件說明:
圖片
最后,它提醒您啟動一個新的 shell 或使用 env 文件。我注意到所有這些都有一種新的更友好的口吻——就好像,也許,Rust 現在很流行!
好的,現在我應該可以使用 Tauri 的單行命令:
圖片
請注意,我們已經進入了 Tauri 2.0 的測試版。
模板安裝選項認識到工具包的多樣性。我可以使用 .NET,但我將使用 JavaScript 來獲得更通用的視圖。顯然,Rust 也可用。
圖片
我保留了我稍微舊的 npm/node 組合并構建了我的模板:
圖片
然后我們在開發環境中運行模板:
圖片
這將構建我們開始所需的所有包,第一次需要幾分鐘。這些將是 Rust 與您的操作系統窗口通信的方式。最終,它將啟動應用程序:
圖片
因此,我們啟動了一個應用程序,它彈出了,在我的托盤中顯示為一個標準的 Mac 應用程序。
好的,讓我們看看它是如何組成的。在我們深入研究之前,請注意,點擊圖標會啟動一個瀏覽器頁面,在文本框中輸入您的姓名并按下按鈕會顯示一個問候語:
圖片
這將幫助我們稍后找出 Rust 的一部分。代碼結構是人們對 Web 應用程序的期望:
圖片
我選擇了原生 JavaScript,因此我們在模板中得到了一個非常原生的index.html:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="stylesheet" href="styles.css" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Tauri App</title>
<script type="module" src="/main.js" defer></script>
</head>
<body>
<div class="container">
<h1>Welcome to Tauri!</h1>
<div class="row">
<a target="_blank">
<img src="/assets/tauri.svg" class="logo tauri" alt="Tauri logo" />
</a>
<a target="_blank" >
<img src="/assets/javascript.svg" class="logo vanilla" alt="JavaScript logo" />
</a>
</div>
<p>Click on the Tauri logo to learn more about the framework</p>
<form class="row" id="greet-form">
<input id="greet-input" placeholder="Enter a name..." />
<button type="submit">Greet</button>
</form>
<p id="greet-msg"></p>
</div>
</body>
</html>
中央div顯示一個錨點中的圖像,該錨點處理鏈接行為。請注意,JavaScript 位于main.js中,窗口本身的應用程序標題與這里定義的標題不同。我們有一個非常老式的form用于輸入文本。因此,我們知道我們將不得不處理該表單以提取輸入的名稱,并將結果放置在最終的p中。這是main.js的內容:
const { invoke } = window.__TAURI__.core;
let greetInputEl;
let greetMsgEl;
async function greet() {
// Learn more about Tauri commands at https://tauri.app/v1/guides/features/command
greetMsgEl.textContent = await invoke("greet", { name: greetInputEl.value });
}
window.addEventListener("DOMContentLoaded", () => {
greetInputEl = document.querySelector("#greet-input");
greetMsgEl = document.querySelector("#greet-msg");
document.querySelector("#greet-form").addEventListener("submit", (e) => {
e.preventDefault();
greet();
});
});
在選擇活動元素并為表單按鈕添加事件偵聽器之后,我們會運行一個處理輸入并將之粘貼到輸出段落的函數。這需要調用一些 Rust,所以我們了解一些它的工作原理。
如果我們回到在生成區域中的主目錄,我們會注意到 src-tauri:
而有些 Rust 代碼位于 src 中的 main.rs 中:
// Learn more about Tauri commands at https://tauri.app/v1/guides/features/command
#[tauri::command]
fn greet(name: &str) -> String {
format!("Hello, {}! You've been greeted from Rust!", name)
}
fn main() {
tauri::Builder::default()
.plugin(tauri_plugin_shell::init())
.invoke_handler(tauri::generate_handler![greet])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
我們能夠看到 JavaScript 中的 invoke 調用到達處理字符串的 Rust greet 函數。這是很好的一點,因為我們可以使用 Tauri 幫我們管理的 Rust 函數。(我們還需要了解 greet 函數的生成器。)
要顯示的最終文件是以 JSON 格式的,用于控制窗口本身,tauri.conf.json:
{
"productName": "thenewstack",
"version": "0.0.0",
"identifier": "com.tauri.dev",
"build": {
"frontendDist": "../src"
},
"app": {
"withGlobalTauri": true,
"windows": [
{
"title": "thenewstack",
"width": 800,
"height": 600
}
],
"security": {
"csp": null
}
},
"bundle": {
"active": true,
"targets": "all",
"icon": [
"icons/32x32.png",
"icons/128x128.png",
...
]
}
}
為了確保我們理解了一切,讓我們設定一個可識別的目標,并稱呼一個友好的新問候者。
“我們改變上述目標以使其更小,并添加一個唯一的標識符:
{
...
"identifier": "io.thenewsatck",
...
"app": {
"windows": [
{
"title": "Welcome to TheNewStack",
"width": 600,
"height": 200
}
],
...
},
...
}
然后我們適當地更改消息代碼。這將強迫構建檢查更改。
最后,我們運行完整構建,以查看它對可執行文件所做的更改。
圖片
當然,這是需要時間的,因為它是第一次。結果是dmg和app文件。一旦我們把app移動到應用程序文件夾中,我們可以像正常的mac應用程序一樣執行它:
圖片
應用程序大小仍然有點胖(10.7 mb),但我沒有做任何事情來精簡自動添加到模板的板條箱。
結論
我認為我們很快從零變英雄與模板,盡管允許一系列 JavaScript 框架的靈活性確實讓一切都變得有點復雜。我想知道更武斷的方法是否會更好。但總體而言,我認為 Tauri 仍然是打造桌面應用程序而無需擔心窗口內部的一個非常可靠的解決方案。