像是 Electron 的框架雖然便利,但常常會面臨「應用程式體積過大」「佔用記憶體」等問題。
Tauri 利用作業系統原生的 WebView,並以 Rust 作為後端,旨在打造「小巧快速且安全」的桌面應用程式。
本指南假設讀者為 Tauri 初學者,將以「專有名詞的意義 → 實際程式碼 → 如何使用」的流程,逐步引導。
Tauri 是一個「跨平台的應用程式開發工具包」,可以從一個代碼庫中創建適用於 Windows、macOS 和 Linux 等平台的桌面應用程式。
其結構包括負責畫面顯示的「前端部分(Web)」及與 OS 功能互動的「後端部分(Rust)」,兩者以進程分開運行,透過專用的 IPC(進程間通信)安全地進行資料交換。
相較於 Electron 內建獨立的瀏覽器(Chromium),Tauri 使用OS標準的 WebView,因此可以有效降低安裝檔案的大小和內存使用量,這是其特點之一。
閱讀 Tauri 的官方文檔或文章時,會頻繁出現「WebView」「IPC」「命令」「插件」等術語,因此一開始就應該先了解。
WebView 是「作業系統提供的小型瀏覽器」,用來在 Tauri 應用的窗口內部顯示 HTML/JS。
IPC(進程間通信)則是「進程間通信」,Tauri 提供了一個獨特的機制,協助從前端(JavaScript)調用後端(Rust 函數)。
Tauri 的「命令」是指在 Rust 端使用 #[tauri::command] 標記的函數,可以被 JavaScript 透過 invoke() 調用的端點,這樣理解起來會更容易。
開始使用 Tauri 之前,需要安裝 Rust 的工具鏈(rustup / cargo),以及 Node.js 和包管理器(npm / pnpm / yarn 等)。
在此基礎上,使用 Tauri 官方提供的 create-tauri-app,可以選擇模板快速創建專案的雛型。
https://www.rust-lang.org/ 安裝# 使用 npm
npm create tauri-app@latest my-tauri-app
# 使用 pnpm
pnpm create tauri-app@latest my-tauri-app
# 使用 yarn
yarn create tauri-app my-tauri-app
執行命令後,將會以互動形式詢問應用名稱、組合 ID、前端框架(Vanilla / React / Vue / Svelte 等)。
回答完所有問題後,將會在 my-tauri-app 目錄下創建前端與 src-tauri 目錄,並隨時可運行。
打開生成的專案,可以看到至少有「前端部分的資料夾」和「src-tauri 資料夾」兩個。
前端部分(如:src/ 或 app/ 目錄)是按照正常 Web 應用的方式編寫 HTML/CSS/JS 或 React/Vue 代碼的地方。
src-tauri 資料夾中包含 Rust 的源代碼和配置文件(tauri.conf.json 等),這裡負責管理窗口設置、菜單、圖標和構建設置等。
結構示意(簡化):
my-tauri-app/
package.json
src/ # 前端 (例: Vite + React)
public/
src-tauri/
src/
main.rs # Rust 的進入點
tauri.conf.json
Cargo.toml # Rust 的依賴關係
理解這種結構後,就不會在「編輯 Web 部分還是添加原生功能」時感到迷惘。
當雛形完成後,首先要在本地啟動開發用伺服器。
在 Tauri 中,前端開發伺服器(如 Vite)會運行,同時 Rust 端會編譯 Tauri 應用,並作為實際的桌面窗口顯示。
cd my-tauri-app
npm install # 若還未安裝則安裝依賴包
npm run tauri dev # 以 Tauri 開發模式啟動
成功後,控制台將顯示構建日誌,過一段時間後,將會出現一個 OS 原生窗口,並在其中顯示前端畫面。
此時的功能雖然還是很簡單,但應該能感受到「正在作為應用而不是瀏覽器運行」。
接下來便是 Tauri 的特色部分。在 Rust 端定義名為「命令」的函數,並使之可以從 JavaScript 調用。
命令是指「普通的 Rust 函數加上 #[tauri::command] 屬性」,Tauri 會通過 IPC 協助前端的調用。
src-tauri/src/main.rs 的最小範例:
// src-tauri/src/main.rs
// 問候命令
#[tauri::command]
fn greet(name: &str) -> String {
format!("你好,{}!來自 Rust 的訊息。", name)
}
fn main() {
tauri::Builder::default()
// 在這裡註冊要使用的命令函數
.invoke_handler(tauri::generate_handler![greet])
.run(tauri::generate_context!())
.expect("執行 tauri 應用時發生錯誤");
}
重點在於 invoke_handler(tauri::generate_handler![greet]) 部分,這裡列舉的 greet 函數就只能從前端調用。
這種機制通過「限制使用的原生 API,關閉不必要的部分」來提高安全性,這也是 Tauri 的特點之一。
在 Rust 端定義了 greet 命令後,現在來從前端調用它。
Tauri 提供了名為 @tauri-apps/api 的包,通過其中的 invoke 函數可以輕鬆呼叫 Rust 命令。
例:簡單的前端示範(Vite + Vanilla JS)
<!-- index.html 的一部分 (示意) -->
<body>
<h1>Tauri 範例</h1>
<input id="name-input" placeholder="請輸入名字" />
<button id="greet-button">問候</button>
<p id="result"></p>
<script type="module">
import { invoke } from '@tauri-apps/api/tauri';
const input = document.querySelector('#name-input');
const button = document.querySelector('#greet-button');
const result = document.querySelector('#result');
button.addEventListener('click', async () => {
const name = input.value || '世界';
// 呼叫 Rust 的 greet 命令
const message = await invoke('greet', { name });
result.textContent = String(message);
});
</script>
</body>
這裡的重點是,invoke('greet', { name }) 的第一個參數是 Rust 端的函數名稱(仍為蛇形命名),而第二個參數的對象則與參數名稱對應。
理解這一點後,就能夠自由地從前端調用 Rust 的處理邏輯(如檔案操作或 OS 資訊獲取等)。
src-tauri/tauri.conf.json 是控制應用名稱、窗口尺寸、啟動時 URL 等 Tauri 整體行為的重要設定檔。
透過編輯這個檔案,可以調整「啟動時最大化」「自訂標題列」「指定構建時的圖標」等。
簡單範例(摘錄示意):
{
"package": {
"productName": "我的 Tauri 應用",
"version": "0.1.0"
},
"tauri": {
"windows": [
{
"title": "我的 Tauri 應用",
"width": 800,
"height": 600,
"resizable": true
}
],
"security": {
"csp": null
}
}
}
windows 區塊是每個窗口的設定,security 則可進行內容安全政策等安全性設定。
雖然一開始用預設即可運行,但當想要調整 UI/UX 時,閱讀此檔案將有助於了解「Tauri 在做什麼」。
作為桌面應用,可以嘗試創建一個本地讀寫檔案的範例。
這裡作為「類似記事本的應用」,實現存儲和讀取文本檔案的功能,這些都是以 Rust 命令的形式實現。
Rust 端的範例:
// src-tauri/src/main.rs
use std::fs;
use std::path::PathBuf;
#[tauri::command]
fn save_text(path: String, content: String) -> Result<(), String> {
fs::write(path, content).map_err(|e| e.to_string())
}
#[tauri::command]
fn load_text(path: String) -> Result<String, String> {
fs::read_to_string(path).map_err(|e| e.to_string())
}
fn main() {
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![save_text, load_text])
.run(tauri::generate_context!())
.expect("執行 tauri 應用時發生錯誤");
}
JavaScript 端的調用範例:
import { invoke } from '@tauri-apps/api/tauri';
async function save() {
const content = document.querySelector('#editor').value;
await invoke('save_text', { path: 'note.txt', content });
alert('已保存');
}
async function load() {
const text = await invoke('load_text', { path: 'note.txt' });
document.querySelector('#editor').value = text;
}
這樣一來,就能在應用的當前目錄存儲和讀取 note.txt,不過實際運用上可以結合「打開檔案對話框」等方式,提供更自然的使用體驗。
要增加桌面應用的原生感,利用原生的對話框和通知是很有效的方法。
Tauri 提供了一些直接可從 JavaScript 調用的模組,例如 @tauri-apps/api/dialog 和 @tauri-apps/api/notification。
檔案選擇對話框的範例:
import { open } from '@tauri-apps/api/dialog';
import { invoke } from '@tauri-apps/api/tauri';
async function openFile() {
const selected = await open({
multiple: false,
filters: [{ name: '文本', extensions: ['txt'] }]
});
if (typeof selected === 'string') {
const text = await invoke('load_text', { path: selected });
document.querySelector('#editor').value = text;
}
}
通知的範例:
import { isPermissionGranted, requestPermission, sendNotification } from '@tauri-apps/api/notification';
async function notify() {
let granted = await isPermissionGranted();
if (!granted) {
const permission = await requestPermission();
granted = permission === 'granted';
}
if (granted) {
sendNotification({
title: 'Tauri 通知',
body: '檔案保存完成。'
});
}
}
透過這些 API 的組合,可以輕鬆實現與 OS 的連結,這是在瀏覽器中無法做到的。
在 Tauri 中,不僅可以打開主窗口,還可以打開設定畫面或幫助畫面等子窗口。
透過 JavaScript 使用 @tauri-apps/api/window,可以輕鬆進行窗口的最小化、最大化、新建等操作。
打開新窗口的範例:
import { WebviewWindow } from '@tauri-apps/api/window';
function openSettingsWindow() {
const settings = new WebviewWindow('settings', {
url: 'settings.html',
title: '設定',
width: 400,
height: 300
});
settings.once('tauri://created', () => {
console.log('設定窗口已創建');
});
}
控制窗口狀態的範例:
import { appWindow } from '@tauri-apps/api/window';
async function toggleMaximize() {
const isMaximized = await appWindow.isMaximized();
if (isMaximized) {
await appWindow.unmaximize();
} else {
await appWindow.maximize();
}
}
利用這些功能,能夠創建「主要工作界面」和「在子窗口中顯示日誌或設置」等更像桌面應用的佈局。
Tauri 的設計思想之一是「最小權限」,在應用內部只明確啟用所需的原生 API 和命令。
例如,可以通過 tauri.conf.json 限制不被允許的域名的外部請求,或小心設計指令,以避免不必要地接觸本地檔案或網路。
安全性設定的一個例子(示意):
{
"tauri": {
"security": {
"csp": "default-src 'self'; script-src 'self'; connect-src 'self' https://api.example.com"
},
"allowlist": {
"fs": {
"readFile": true,
"writeFile": true
},
"dialog": {
"open": true
}
}
}
}
在 allowlist 區塊中,可以精細控制哪些檔案系統和對話框 API 的功能被允許,因此能夠讓應用在必要的最低權限範圍內運行。
這使得 Tauri 在「利用 Web 技術構建的桌面應用」的同時,也具備堅固的安全基礎,成為其一大優勢。
當開發進行到一定程度後,需要為用戶構建安裝程式或可執行檔。
Tauri 可以生成適用於各操作系統的原生二進制檔案(.exe / .app / .deb 等),其檔案大小通常比 Electron 小得多。
構建命令範例:
# 釋出構建
npm run tauri build
這樣會在 src-tauri/target/release/ 生成適用於該操作系統的二進制檔案,並進一步生成安裝檔形式的文件(如 Windows 安裝程式)。
接著可以上傳至 GitHub Releases 進行分發,或在內部業務運用中,將其放置在內部存儲中分發給用戶。
Tauri 擁有許多官方和社區製作的插件,可以輕鬆添加 OAuth 認證、儲存和更新功能。
插件作為 Rust 端的依賴進行添加,並可根據需要在設定檔中註冊。
例:在 Cargo.toml 中添加插件(示意)
[dependencies]
tauri = { version = "2.0", features = ["shell-all"] }
tauri-plugin-store = "2.0"
Rust 端註冊插件的代碼範例:
fn main() {
tauri::Builder::default()
.plugin(tauri_plugin_store::Builder::default().build())
.run(tauri::generate_context!())
.expect("執行 tauri 應用時發生錯誤");
}
使用插件可讓「設定的持續化」「自動更新」「執行 OS 的 shell 命令」等功能,採用比自行編寫包裝器更安全與統一的方式來實現。
至此,我們已經體驗了 Tauri 的基本結構、Rust 命令、從 JavaScript 的調用、檔案操作、對話框、安全性、構建等完整過程。
接下來的步驟,建議選擇一個「自己每天都想使用的小工具」,並試著用 Tauri 實現。
例如:
這些應用能充分運用 Web 技術和 Rust 的優勢,能夠強烈感受到 Tauri 的好處。
Tauri 官方的日文文檔和 GitHub 範例也越來越豐富,如果對某些功能感興趣,可以逐步閱讀代碼並逐步引入到自己的應用中,這樣能加深學習效果。
透過這 15 章,若「Tauri 是什麼」「其設計思想是什麼」「如何使用」有了一定的了解,那麼接下來就試著製作一個小型的原型吧。
透過自己喜愛的前端技術和 Rust 的力量,培養出小巧且快速的桌面應用將是一個非常有趣的體驗,並能直接提升技能。
原文出處:https://qiita.com/automation2025/items/c2e5d77c08c37532a3a3