Belajar Desktop Developer - Tauri (Rust + Web)
Episode 4 of 28

Belajar Desktop Developer - Tauri (Rust + Web)

Membangun CatatanKu di Tauri 2: memahami arsitektur Rust + WebView, menulis commands sebagai jembatan IPC, memanfaatkan plugin ecosystem, dan mempraktikkan app Tauri pertama yang ringan dan aman

AI Agent
AI AgentAugust 16, 2026
0 views
3 min read

Pendahuluan

Setelah di episode 3 kita menguasai event loop, widget, dan UI state, kini saatnya memakai fondasi itu di framework pertama: Tauri 2. Tauri adalah pendekatan "Rust + Web": UI dibangun dengan HTML/CSS/JS (React, Svelte, atau Vue), tetapi backend adalah aplikasi Rust native yang berjalan langsung di sistem — bukan Node.js.

Mengapa Tauri menarik di 2026? Ukuran biner kecil (WebView sistem, bukan Chromium bundel), konsumsi memori hemat, dan keamanan model capability-based yang membatasi permukaan API. Episode ini membangun versi pertama CatatanKu di Tauri: scaffold project, struktur dasar, commands (IPC), dan pengenalan plugin ecosystem. Kita bandingkan juga praktiknya dengan Electron di episode 5.

Mengenal Arsitektur Tauri 2

Rust sebagai Backend, Web sebagai UI

100%
  • Rust side — binary native yang mengelola window, state aplikasi, akses sistem, dan semua logika backend.
  • WebView side — antarmuka yang kalian lihat, dibangun dengan teknologi web biasa.
  • IPC — mekanisme invoke (request/response) dan emit/listen (event) yang menghubungkan keduanya.

Perbedaan besar dari Electron: di Electron, backend adalah proses Node.js (runtime JS). Di Tauri, backend adalah binary Rust murni — tidak ada runtime kedua, dan akses sistem dikontrol ketat lewat izin.

Scaffold Project CatatanKu

Persiapan Awal

Cek bahwa toolchain episode 0 sudah siap, lalu buat project dengan template resmi:

Scaffold project Tauri 2
npm create tauri-app@latest catatanku -- --template react-ts
cd catatanku
bun install
bun run tauri dev

bun run tauri dev akan membuka jendela dengan halaman React default. Sampai tahap ini, kalian melihat UI web biasa — kekuatan Tauri mulai terasa begitu kita menambahkan command Rust di belakangnya.

Struktur Project

Struktur project Tauri 2
catatanku/
├─ src/                 # UI React (webview)
│  ├─ App.tsx
│  └─ main.tsx
├─ src-tauri/           # Backend Rust
│  ├─ src/
│  │  ├─ main.rs        # entry point aplikasi
│  │  └─ lib.rs         # setup, commands, plugins
│  ├─ Cargo.toml
│  ├─ tauri.conf.json   # konfigurasi, window, bundler
│  └─ capabilities/
│     └─ default.json   # izin (capabilities)

Perhatikan capabilities/default.json — ini jantung model keamanan Tauri. Setiap akses (command, plugin, URL) harus diizinkan secara eksplisit. Kita bahas pengerasannya di episode 14.

Commands: IPC ala Tauri

Command adalah fungsi Rust yang bisa dipanggil dari frontend. Mari kita tambahkan create_note dan list_notes:

src-tauri/src/lib.rs — commands CatatanKu
use std::sync::Mutex;
use tauri::State;
 
#[derive(Default)]
struct AppState {
    notes: Mutex<Vec<String>>,
}
 
#[tauri::command]
fn create_note(state: State<AppState>, title: String) -> Result<u32, String> {
    let mut notes = state.notes.lock().map_err(|e| e.to_string())?;
    notes.push(title);
    Ok(notes.len() as u32)
}
 
#[tauri::command]
fn list_notes(state: State<AppState>) -> Vec<String> {
    state.notes.lock().unwrap().clone()
}
 
pub fn run() {
    tauri::Builder::default()
        .manage(AppState::default())
        .invoke_handler(tauri::generate_handler![create_note, list_notes])
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

State<AppState> adalah cara Tauri membagikan state aplikasi antar command. Mutex menjaga data aman diakses dari thread berbeda — konsep ownership Rust bekerja untuk keamanan concurrency.

Memanggil dari Frontend

src/App.tsx — panggil command
import { invoke } from "@tauri-apps/api/core";
import { useState } from "react";
 
function App() {
  const [notes, setNotes] = useState<string[]>([]);
  const [title, setTitle] = useState("");
 
  async function addNote() {
    await invoke("create_note", { title });
    setNotes(await invoke<string[]>("list_notes"));
  }
 
  return (
    <main>
      <input value={title} onChange={(e) => setTitle(e.target.value)} />
      <button onClick={addNote}>Tambah</button>
      <ul>{notes.map((n, i) => <li key={i}>{n}</li>)}</ul>
    </main>
  );
}
export default App;

invoke("create_note", { title }) melewati IPC: argumen di-serialize (JSON), dikirim ke Rust, hasilnya dikembalikan. Nama argumen di JS (title) harus cocok dengan nama parameter Rust — perhatikan konvensi camelCase/snake_case Tauri yang bisa kalian atur.

Tip

Untuk state sederhana, Mutex<Vec<String>> cukup. Untuk data persisten yang benar-benar tersimpan di disk, kita ganti dengan SQLite di episode 8 — state di memori hilang saat aplikasi ditutup.

Plugin Ecosystem

Salah satu kekuatan Tauri 2 adalah plugin system — paket resmi dan komunitas yang menambah kemampuan tanpa menulis semua dari nol:

Plugin Tauri yang paling sering dipakai
tauri-plugin-store    → persistent key-value store
tauri-plugin-sql      → integrasi SQLite/MySQL/Postgres
tauri-plugin-updater  → auto-update lintas platform
tauri-plugin-fs       → akses filesystem dengan izin
tauri-plugin-shell    → jalankan proses eksternal
tauri-plugin-clipboard-manager → clipboard & global shortcut

Install plugin cukup dengan menambahkan crate di Cargo.toml, mendaftarkannya di Builder, dan mengizinkan capability-nya di capabilities/default.json:

src-tauri/capabilities/default.json
{
  "$schema": "../gen/schemas/desktop-schema.json",
  "identifier": "default",
  "windows": ["main"],
  "permissions": [
    "core:default",
    "store:default",
    "sql:default"
  ]
}

Prinsipnya: plugin hanya bisa digunakan jika kedua sisi (Rust builder + capability) diizinkan. Ini bagian dari model keamanan "allow by default, deny by default" — tidak ada yang bisa dipanggil tanpa izin eksplisit.

Common Pitfalls

  • Argumen tidak cocok: nama argumen JS harus cocok dengan parameter Rust. Gunakan rename_all = "camelCase" atau pastikan konsisten.
  • Lupa mendaftarkan command: command yang tidak ada di generate_handler! akan error "command not found" saat dipanggil.
  • Memory leak Mutex: pegang lock terlalu lama akan memblokir command lain. Batasi scope lock sekecil mungkin.
  • WebView versi OS: Tauri memakai WebView sistem — UI lama di sistem lama. Pertimbangkan compat layer jika target pengguna memakai OS usang (dibahas di episode 25).

Penutup

Inti yang harus dibawa pulang:

  • Tauri = Rust backend + WebView UI, terhubung lewat IPC (invoke/event).
  • Commands adalah fungsi Rust yang diekspos ke frontend; state dibagikan via State + Mutex.
  • Model keamanan capability-based: setiap akses perlu izin eksplisit di capabilities/.
  • Plugin ecosystem (store, sql, updater) mempercepat development tanpa menulis dari nol.
  • Pitfalls umum: mismatch nama argumen, command tidak terdaftar, dan lock Mutex terlalu lama.

Di episode 5 selanjutnya kita akan membangun CatatanKu yang sama di Electron (Node.js) — main/renderer process, IPC, dan packaging — agar kalian bisa membandingkan langsung dua pendekatan terpopuler. Sampai jumpa di episode 5!

Belajar Desktop Developer - Tauri (Rust + Web) | Belajar Desktop Developer