Tauri v2 — Xây dựng Desktop App siêu nhẹ với Vue.js và Rust

Posted on: 4/26/2026 10:12:47 PM

< 8 MB Kích thước bundle trung bình
30-50 MB RAM khi chạy (vs 200-300 MB Electron)
< 0.5s Thời gian khởi động
96% Nhỏ hơn so với Electron

Nếu bạn từng dùng Electron để xây ứng dụng desktop, hẳn bạn đã quen với việc ship cả một trình duyệt Chromium nặng hơn 100 MB chỉ để hiển thị UI. Tauri v2 đưa ra cách tiếp cận hoàn toàn khác: sử dụng WebView có sẵn trên hệ điều hành kết hợp với backend viết bằng Rust — ngôn ngữ nổi tiếng về hiệu năng và an toàn bộ nhớ. Kết quả là ứng dụng desktop (và cả mobile) chỉ từ 3-8 MB, khởi động dưới nửa giây.

Kiến trúc Tauri v2

Tauri sử dụng mô hình multi-process tương tự trình duyệt, nhưng gọn nhẹ hơn nhiều. Có hai thành phần chính:

graph TB
    subgraph "Tauri Core (Rust)"
        A["tauri::App"] --> B["Window Manager
(TAO)"] A --> C["WebView Renderer
(WRY)"] A --> D["Plugin System"] A --> E["IPC Bridge"] D --> F["fs / dialog / shell
http / notification
updater / sql"] end subgraph "Frontend (Vue.js)" G["Vue Components"] --> H["@tauri-apps/api"] H --> E end subgraph "OS Layer" C --> I["WebView2
(Windows)"] C --> J["WKWebView
(macOS/iOS)"] C --> K["WebKitGTK
(Linux)"] B --> L["Native Window"] end style A fill:#e94560,stroke:#fff,color:#fff style G fill:#42b883,stroke:#fff,color:#fff style I fill:#f8f9fa,stroke:#e0e0e0,color:#2c3e50 style J fill:#f8f9fa,stroke:#e0e0e0,color:#2c3e50 style K fill:#f8f9fa,stroke:#e0e0e0,color:#2c3e50

Kiến trúc tổng quan Tauri v2 — Rust core + WebView hệ thống + Frontend framework

  • TAO — thư viện quản lý cửa sổ (window creation, event loop, system tray) viết bằng Rust, hỗ trợ Windows/macOS/Linux/Android/iOS.
  • WRY — lớp abstraction cho WebView, tự động chọn WebView2 trên Windows, WKWebView trên macOS, WebKitGTK trên Linux. Không bundle Chromium → tiết kiệm >100 MB.
  • IPC Bridge — giao tiếp JavaScript ↔ Rust qua hàm invoke(), serialize/deserialize tự động với serde.

Tại sao không phải Electron?

Tiêu chí Tauri v2 Electron
Bundle size 3–8 MB 80–200 MB
RAM khi idle 30–50 MB 200–300 MB
Startup time < 0.5 giây 1–2 giây
Backend Rust (memory-safe) Node.js
Renderer System WebView Bundled Chromium
Mobile support iOS + Android (v2) Không hỗ trợ
Security model Capability-based (deny by default) Permissive (phải tự lock down)
Auto-updater Built-in, delta updates electron-updater (third-party)

Khi nào vẫn nên chọn Electron?

Nếu ứng dụng cần rendering pixel-perfect đồng nhất trên mọi OS (như Figma, Spotify), hoặc phụ thuộc nặng vào Node.js ecosystem và native modules, Electron vẫn là lựa chọn hợp lý. Tauri phù hợp hơn cho internal tools, utilities, và ứng dụng cần bundle nhỏ + bảo mật chặt.

Khởi tạo dự án Tauri + Vue.js

Tauri hỗ trợ mọi frontend framework, nhưng Vue.js là một trong những lựa chọn phổ biến nhất nhờ hệ sinh thái phong phú và Vite build siêu nhanh.

# Tạo project mới với Vue + TypeScript
npm create tauri-app@latest my-app -- --template vue-ts

# Cấu trúc thư mục
my-app/
├── src/              # Vue frontend
│   ├── App.vue
│   ├── main.ts
│   └── components/
├── src-tauri/        # Rust backend
│   ├── src/
│   │   ├── main.rs   # Entry point
│   │   └── lib.rs    # Commands
│   ├── Cargo.toml
│   ├── tauri.conf.json
│   └── capabilities/ # Permission declarations
└── package.json

IPC — Giao tiếp giữa Vue và Rust

Cốt lõi sức mạnh của Tauri nằm ở IPC (Inter-Process Communication). Frontend gọi hàm Rust qua invoke(), Rust xử lý logic nặng rồi trả kết quả. Mọi thứ đều type-safe nhờ serde.

// src-tauri/src/lib.rs
use tauri::command;
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize)]
pub struct SystemInfo {
    pub cpu_usage: f64,
    pub memory_total: u64,
    pub memory_used: u64,
    pub os_name: String,
}

#[command]
async fn get_system_info() -> Result<SystemInfo, String> {
    // Logic Rust chạy native, không qua V8/Node.js
    Ok(SystemInfo {
        cpu_usage: 23.5,
        memory_total: 16_000_000_000,
        memory_used: 8_500_000_000,
        os_name: std::env::consts::OS.to_string(),
    })
}

#[command]
async fn process_file(path: String) -> Result<String, String> {
    let content = std::fs::read_to_string(&path)
        .map_err(|e| e.to_string())?;
    // Xử lý file với hiệu năng Rust native
    Ok(format!("Processed {} bytes", content.len()))
}

pub fn run() {
    tauri::Builder::default()
        .invoke_handler(tauri::generate_handler![
            get_system_info,
            process_file
        ])
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}
<!-- src/components/SystemMonitor.vue -->
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { invoke } from '@tauri-apps/api/core'

interface SystemInfo {
  cpu_usage: number
  memory_total: number
  memory_used: number
  os_name: string
}

const info = ref<SystemInfo | null>(null)

onMounted(async () => {
  // Gọi hàm Rust từ Vue — type-safe, async
  info.value = await invoke<SystemInfo>('get_system_info')
})

async function handleFile(path: string) {
  const result = await invoke<string>('process_file', { path })
  console.log(result)
}
</script>

<template>
  <div v-if="info">
    <p>OS: {{ info.os_name }}</p>
    <p>CPU: {{ info.cpu_usage }}%</p>
    <p>RAM: {{ (info.memory_used / 1e9).toFixed(1) }} /
           {{ (info.memory_total / 1e9).toFixed(1) }} GB</p>
  </div>
</template>

Type-safety end-to-end

Rust struct được serialize qua serde → JSON → TypeScript interface. Nếu bạn dùng tauri-specta, type bindings được tự động generate từ Rust sang TypeScript, đảm bảo frontend và backend luôn đồng bộ.

Bảo mật Capability-Based

Đây là điểm khác biệt lớn nhất với Electron. Tauri v2 áp dụng nguyên tắc deny by default — mọi API hệ thống đều bị chặn cho đến khi được khai báo rõ ràng trong file capability.

graph LR
    A["Vue Component
invoke('read_file')"] --> B{"Capability
Check"} B -->|"Allowed"| C["Rust Command
thực thi"] B -->|"Denied"| D["Error:
Permission Denied"] C --> E["Trả kết quả
về Frontend"] style A fill:#42b883,stroke:#fff,color:#fff style B fill:#ff9800,stroke:#fff,color:#fff style C fill:#4CAF50,stroke:#fff,color:#fff style D fill:#e94560,stroke:#fff,color:#fff

Luồng kiểm tra permission trong Tauri v2

// src-tauri/capabilities/main.json
{
  "identifier": "main-capability",
  "description": "Permissions cho cửa sổ chính",
  "windows": ["main"],
  "permissions": [
    "core:default",
    {
      "identifier": "fs:allow-read-text-file",
      "allow": [
        { "path": "$APPDATA/**" },
        { "path": "$DOCUMENT/**" }
      ]
    },
    "dialog:allow-open",
    "notification:default"
  ]
}

Mỗi cửa sổ (window) có capability riêng. Một cửa sổ settings có thể truy cập file system, nhưng cửa sổ webview hiển thị nội dung bên ngoài thì không. Điều này giúp tuân thủ SOC 2, HIPAA dễ dàng hơn vì attack surface được thu hẹp tối đa.

Plugin System

Tauri v2 có hệ thống plugin phong phú, chia thành official plugins (do Tauri team duy trì) và community plugins:

Plugin Chức năng Use case
@tauri-apps/plugin-fs Đọc/ghi file system Text editor, file manager
@tauri-apps/plugin-dialog Native file dialog, message box Open/Save file picker
@tauri-apps/plugin-http HTTP client (bypass CORS) API calls, download
@tauri-apps/plugin-notification System notification Alert, reminder
@tauri-apps/plugin-updater Auto-update + delta updates Silent app updates
@tauri-apps/plugin-sql SQLite / MySQL / PostgreSQL Local database
@tauri-apps/plugin-store Key-value persistent storage Settings, preferences
@tauri-apps/plugin-shell Chạy command/script CLI wrapper, automation

Mobile Support — Cùng codebase cho Desktop và Mobile

Tauri v2 mang tới khả năng build cho iOS và Android từ cùng một codebase. Frontend Vue.js được render trên WKWebView (iOS) hoặc Android WebView, backend Rust compile sang target tương ứng.

# Thêm mobile target
npm run tauri android init
npm run tauri ios init

# Build và chạy trên thiết bị/emulator
npm run tauri android dev
npm run tauri ios dev

Lưu ý về Mobile

Mobile support trong Tauri v2 vẫn đang hoàn thiện. Không phải tất cả plugin đều hỗ trợ mobile. Với các ứng dụng mobile phức tạp cần native UI sâu (camera, sensor, map), React Native hoặc Flutter vẫn phù hợp hơn. Tauri mobile lý tưởng cho ứng dụng dạng content, dashboard, hoặc utility.

Auto-Updater với Delta Updates

Tauri tích hợp sẵn cơ chế cập nhật ứng dụng — không cần thư viện bên thứ ba. Đặc biệt, nó hỗ trợ delta updates: chỉ tải phần thay đổi (1-5 MB) thay vì toàn bộ app.

// src-tauri/src/lib.rs — Cấu hình updater
use tauri_plugin_updater::UpdaterExt;

pub fn run() {
    tauri::Builder::default()
        .plugin(tauri_plugin_updater::Builder::new().build())
        .setup(|app| {
            let handle = app.handle().clone();
            tauri::async_runtime::spawn(async move {
                let updater = handle.updater().unwrap();
                if let Some(update) = updater.check().await.unwrap() {
                    println!("Update available: {}", update.version);
                    update.download_and_install(|_, _| {}, || {}).await.unwrap();
                }
            });
            Ok(())
        })
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

Production Workflow

graph LR
    A["npm run build
(Vite → dist/)"] --> B["cargo build
--release"] B --> C{"Target OS"} C --> D["Windows
.msi / .exe
~5 MB"] C --> E["macOS
.dmg / .app
~4 MB"] C --> F["Linux
.deb / .AppImage
~6 MB"] C --> G["Android
.apk
~8 MB"] C --> H["iOS
.ipa"] style A fill:#42b883,stroke:#fff,color:#fff style B fill:#e94560,stroke:#fff,color:#fff style D fill:#f8f9fa,stroke:#e0e0e0,color:#2c3e50 style E fill:#f8f9fa,stroke:#e0e0e0,color:#2c3e50 style F fill:#f8f9fa,stroke:#e0e0e0,color:#2c3e50 style G fill:#f8f9fa,stroke:#e0e0e0,color:#2c3e50 style H fill:#f8f9fa,stroke:#e0e0e0,color:#2c3e50

Pipeline build đa nền tảng của Tauri v2

# Build cho production
npm run tauri build

# Với CI/CD (GitHub Actions)
# Tauri cung cấp sẵn action: tauri-apps/tauri-action
# Tự động build cho Windows, macOS, Linux và tạo release

Hiệu năng thực tế — Benchmark

graph LR
    subgraph "Bundle Size"
        A1["Tauri: 5 MB"] ---|vs| A2["Electron: 150 MB"]
    end
    subgraph "RAM Usage"
        B1["Tauri: 40 MB"] ---|vs| B2["Electron: 250 MB"]
    end
    subgraph "Startup"
        C1["Tauri: 0.3s"] ---|vs| C2["Electron: 1.5s"]
    end
    style A1 fill:#4CAF50,stroke:#fff,color:#fff
    style A2 fill:#e94560,stroke:#fff,color:#fff
    style B1 fill:#4CAF50,stroke:#fff,color:#fff
    style B2 fill:#e94560,stroke:#fff,color:#fff
    style C1 fill:#4CAF50,stroke:#fff,color:#fff
    style C2 fill:#e94560,stroke:#fff,color:#fff

So sánh hiệu năng Tauri v2 vs Electron (ứng dụng todo-app tương đương)

Các con số trên đến từ benchmark cộng đồng với ứng dụng có chức năng tương đương. Sự chênh lệch chủ yếu do Tauri không bundle Chromium (~120 MB) và không chạy Node.js runtime (~50 MB RAM overhead).

Khi nào nên chọn Tauri v2?

Phù hợp Cân nhắc thêm
Internal tools, dashboard, admin panel App cần pixel-perfect cross-OS rendering
CLI wrapper với GUI đẹp Phụ thuộc nặng vào Node.js native modules
Utility app (converter, editor nhẹ) Team chưa quen Rust (learning curve)
App cần bảo mật cao (fintech, healthcare) Cần hệ sinh thái plugin rộng như Electron
Cross-platform desktop + mobile từ 1 codebase Mobile app phức tạp cần native UI sâu

Mẹo cho team đã biết Vue.js

Nếu team đã có kinh nghiệm Vue.js + Vite, chi phí chuyển sang Tauri rất thấp — frontend code gần như giữ nguyên. Phần Rust backend chỉ cần viết các command đơn giản ban đầu, sau đó mở rộng dần khi cần tương tác sâu với hệ thống.

Lộ trình phát triển

10/2024
Tauri 2.0 GA — Ra mắt chính thức với mobile support, plugin system mới, capability-based security.
Q1 2025
Tauri 2.1-2.2 — Cải thiện plugin ecosystem, Swift/Kotlin bindings cho mobile plugins.
Q1 2026
Tauri 2.4 — Phiên bản stable mới nhất, cải thiện security audit và plugin compatibility.
Tương lai
Tauri 3.0 — Đang phát triển, hướng tới WebView rendering tùy chỉnh sâu hơn và cải thiện mobile experience.

Kết luận

Tauri v2 không chỉ là một "Electron nhẹ hơn" — nó đại diện cho một triết lý thiết kế khác: tận dụng tối đa những gì hệ điều hành đã có thay vì bundle mọi thứ. Với Rust backend an toàn bộ nhớ, WebView hệ thống, security model chặt chẽ, và khả năng target cả desktop lẫn mobile, Tauri v2 là lựa chọn đáng cân nhắc cho mọi developer Vue.js muốn đưa ứng dụng web ra khỏi trình duyệt.

Với bản 2.4.2 stable hiện tại và cộng đồng đang phát triển nhanh, đây là thời điểm tốt để bắt đầu tìm hiểu và thử nghiệm Tauri cho dự án tiếp theo.

Tham khảo