Розробка десктоп-приложення на Tauri
Tauri — фреймворк для десктоп-приложень, де бекенд написаний на Rust, а фронтенд — будь-який веб-стек. На відміну від Electron, Tauri не поставляє власний Chromium: використовується системний WebView (WebKit на macOS/Linux, WebView2 на Windows). Результат — дистрибутив від 4 до 15 МБ проти 80+ МБ у Electron.
Архітектура
Frontend (HTML/CSS/JS → будь-який фреймворк)
↕ invoke() / events
Tauri Core (Rust)
↕ системні вклики
ОС (файлова система, нотифікації, трей)
Весь небезпечний код виконується в Rust. Фронтенд може викликати лише явно експонировані Rust-команди через invoke.
Створення проекта
# Попередньо: Rust + системні залежності
# macOS: xcode-select --install
# Windows: Visual Studio Build Tools + WebView2
# Linux: webkit2gtk, libayatana-appindicator
npm create tauri-app@latest
# Вибираємо: TypeScript, React, Vite
Структура проекта:
my-app/
├── src/ # React/Vue/Svelte фронтенд
├── src-tauri/
│ ├── src/
│ │ ├── main.rs # точка входу Rust
│ │ └── lib.rs # команди та плагіни
│ ├── Cargo.toml
│ └── tauri.conf.json
├── package.json
└── vite.config.ts
Rust-команди: основа взаємодії
// src-tauri/src/lib.rs
use tauri::State;
use std::sync::Mutex;
struct AppState {
counter: Mutex<i32>,
}
// Проста команда
#[tauri::command]
fn greet(name: &str) -> String {
format!("Hello, {}!", name)
}
// Асинхронна команда зі станом
#[tauri::command]
async fn increment(state: State<'_, AppState>) -> Result<i32, String> {
let mut counter = state.counter.lock().map_err(|e| e.to_string())?;
*counter += 1;
Ok(*counter)
}
// Команда з доступом до файлової системи
#[tauri::command]
async fn read_file(path: String) -> Result<String, String> {
std::fs::read_to_string(&path).map_err(|e| e.to_string())
}
pub fn run() {
tauri::Builder::default()
.manage(AppState { counter: Mutex::new(0) })
.invoke_handler(tauri::generate_handler![greet, increment, read_file])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
Виклик Rust-команд з фронтенду
// src/api/tauri.ts
import { invoke } from '@tauri-apps/api/core';
export async function greet(name: string): Promise<string> {
return invoke('greet', { name });
}
export async function increment(): Promise<number> {
return invoke('increment');
}
// Використання в React компоненті
function App() {
const [count, setCount] = useState(0);
const handleIncrement = async () => {
const newCount = await increment();
setCount(newCount);
};
return <button onClick={handleIncrement}>Count: {count}</button>;
}
Система подій
// Rust → Frontend
use tauri::{Manager, Emitter};
#[tauri::command]
async fn start_long_task(app: tauri::AppHandle) {
tokio::spawn(async move {
for i in 0..=100 {
tokio::time::sleep(tokio::time::Duration::from_millis(50)).await;
app.emit("progress", i).unwrap();
}
app.emit("task-complete", "done").unwrap();
});
}
// Frontend — підписка на події
import { listen } from '@tauri-apps/api/event';
const unlisten = await listen<number>('progress', (event) => {
setProgress(event.payload);
});
await invoke('start_long_task');
Плагіни екосистеми
# src-tauri/Cargo.toml
[dependencies]
tauri-plugin-fs = "2"
tauri-plugin-dialog = "2"
tauri-plugin-notification = "2"
tauri-plugin-shell = "2"
tauri-plugin-store = "2"
pub fn run() {
tauri::Builder::default()
.plugin(tauri_plugin_fs::init())
.plugin(tauri_plugin_dialog::init())
.run(tauri::generate_context!())
.expect("error running app");
}
Сборка та дистрибуція
# Розробка
npm run tauri dev
# Сборка під поточну платформу
npm run tauri build
Вихід:
- macOS:
.app+.dmg - Windows:
.exe(NSIS) +.msi - Linux:
.deb+.AppImage+.rpm
Коли вибирати Tauri замість Electron
Tauri виправданий коли: розмір дистрибутива критичний, потрібна максимальна продуктивність нативного коду, команда знає Rust або готова його освоїти.
Electron виправданий коли: потрібна однакова середовище виконання без залежності від системного WebView, команда чисто JavaScript/TypeScript, приложение активно використовує экосистему npm-пакетів в основному процесі.
Різниця в розмірі: Tauri ~8 МБ, Electron ~120 МБ. Пам'ять: Tauri 30-60 МБ проти Electron 100-200 МБ при старті.







