Membangun Aplikasi Multi-Platform Efisien: Reusabilitas Logika Bisnis dengan Tauri, WebAssembly, dan Rust
1. Pendahuluan
Di dunia pengembangan aplikasi modern, kebutuhan untuk menjangkau pengguna di berbagai platform semakin meningkat. Dari aplikasi web yang diakses di browser, hingga aplikasi desktop yang berjalan secara native, developer seringkali dihadapkan pada tantangan untuk menulis ulang logika bisnis yang sama berkali-kali. Duplikasi kode ini tidak hanya memakan waktu tetapi juga meningkatkan potensi bug dan mempersulit pemeliharaan.
Bayangkan Anda memiliki aplikasi web yang sukses dengan logika validasi data yang kompleks, algoritma perhitungan keuangan, atau pemrosesan gambar yang unik. Sekarang, tim Anda ingin meluncurkan versi desktop untuk pengguna yang membutuhkan performa dan integrasi sistem operasi yang lebih baik. Apakah Anda akan menulis ulang semua logika tersebut di bahasa pemrograman native desktop seperti C# atau Swift? Tentu saja tidak, jika ada cara yang lebih efisien!
Di sinilah Tauri, WebAssembly (Wasm), dan Rust masuk sebagai kombinasi yang powerful. Artikel ini akan memandu Anda bagaimana memanfaatkan ketiganya untuk membangun aplikasi multi-platform yang efisien, dengan fokus pada reusabilitas logika bisnis inti. Kita akan melihat bagaimana kode Rust yang sama dapat dikompilasi menjadi WebAssembly untuk digunakan di browser, sekaligus menjadi bagian dari aplikasi desktop Tauri Anda.
2. Mengapa Tauri, WebAssembly, dan Rust?
Sebelum kita menyelam ke implementasi, mari pahami mengapa kombinasi ini sangat menarik:
✅ Tauri: Desktop Apps dengan Teknologi Web, Minim Overhead
Tauri adalah framework untuk membangun aplikasi desktop cross-platform menggunakan teknologi web (HTML, CSS, JavaScript/TypeScript). Berbeda dengan Electron yang bundling runtime Chromium dan Node.js, Tauri menggunakan WebView native sistem operasi (misalnya, WebView2 di Windows, WebKit di macOS) dan Rust sebagai backend.
Keunggulan Tauri:
- Ukuran Aplikasi Kecil: Karena menggunakan WebView native, ukuran bundle aplikasi Tauri jauh lebih kecil dibandingkan Electron.
- Performa Native: Backend Rust memungkinkan interaksi yang cepat dengan sistem operasi dan resource hardware.
- Keamanan: Desain Tauri mengutamakan keamanan, dengan sandbox yang ketat dan kemampuan untuk membatasi akses API.
✅ WebAssembly (Wasm): Performa Native di Browser
WebAssembly adalah format instruksi biner yang dapat dieksekusi oleh browser web modern. Ini memungkinkan Anda untuk menjalankan kode yang ditulis dalam bahasa seperti C/C++, Rust, atau Go dengan performa mendekati native langsung di browser.
Keunggulan Wasm:
- Performa Tinggi: Mendekati kecepatan native, ideal untuk komputasi intensif seperti pemrosesan gambar, video, atau algoritma kompleks.
- Bahasa Pilihan: Anda bisa menggunakan bahasa yang Anda sukai (misalnya Rust) untuk menulis logika inti.
- Keamanan: Berjalan di lingkungan sandbox yang aman, terisolasi dari sistem host.
✅ Rust: Kecepatan, Keamanan, dan Konkurensi
Rust adalah bahasa pemrograman sistem yang berfokus pada kecepatan, keamanan memori, dan konkurensi. Ini adalah pilihan yang sangat baik untuk menulis logika bisnis yang kritis dan performa-sensitif.
Keunggulan Rust:
- Performa: Sangat cepat, sebanding dengan C/C++.
- Keamanan Memori: Sistem ownership dan borrowing Rust mencegah banyak kelas bug terkait memori saat compile time.
- Ekosistem Kuat: Banyak library (crates) yang tersedia, termasuk untuk kompilasi ke WebAssembly.
Sinergi Ketiganya:
- Kita akan menulis logika bisnis inti dalam Rust.
- Kode Rust ini akan dikompilasi ke WebAssembly untuk digunakan di aplikasi web browser.
- Kode Rust yang sama juga akan menjadi backend native untuk aplikasi desktop Tauri.
Dengan pendekatan ini, Anda menulis logika bisnis sekali saja di Rust, dan menggunakannya di dua platform berbeda (web dan desktop) dengan performa optimal dan minim duplikasi.
3. Arsitektur Dasar: Berbagi Logika Bisnis
Ide utamanya adalah memisahkan logika bisnis inti ke dalam sebuah library Rust terpisah. Library ini kemudian akan digunakan oleh dua “kepala” aplikasi yang berbeda:
- Web Frontend: Aplikasi web (misal React, Vue, Svelte) yang akan memanggil logika bisnis Rust melalui WebAssembly.
- Tauri Frontend & Backend: Aplikasi desktop Tauri, di mana frontend web-nya juga memanggil logika Rust via WebAssembly, dan backend Rust-nya sendiri juga dapat memanggil logika Rust yang sama secara langsung.
Berikut adalah gambaran arsitekturnya:
+-------------------+ +-------------------+
| Web Frontend | | Tauri Frontend |
| (React/Vue/Svelte)| | (HTML/CSS/JS) |
| | | |
| - Memuat WASM | | - Memuat WASM |
+-------------------+ +-------------------+
| |
| (Memanggil Fungsi WASM) | (Memanggil Fungsi WASM)
v v
+------------------------------------------------+
| Logika Bisnis Inti (Rust) |
| (Dikompilasi ke WebAssembly .wasm) |
| (Juga Digunakan Langsung oleh Tauri Backend)|
+------------------------------------------------+
^ ^
| |
| (Memanggil Fungsi Rust Native)
|
+------------------------------------------------+
| Tauri Backend (Rust) |
| (Interaksi OS, File System, Network) |
+------------------------------------------------+
4. Langkah 1: Membuat Logika Bisnis dengan Rust
Mari kita mulai dengan membuat library Rust yang berisi logika bisnis kita. Sebagai contoh, kita akan membuat fungsi sederhana untuk memvalidasi alamat email dan membersihkan string.
Pertama, buat proyek library Rust baru:
cargo new core-logic --lib
cd core-logic
Edit src/lib.rs untuk menambahkan logika kita:
// src/lib.rs
// Fungsi untuk membersihkan string dari spasi di awal/akhir dan mengonversi ke lowercase
pub fn clean_string(input: &str) -> String {
input.trim().to_lowercase()
}
// Fungsi untuk memvalidasi format email sederhana
pub fn is_valid_email(email: &str) -> bool {
// Regex yang lebih robust bisa digunakan di sini, ini hanya contoh sederhana
email.contains('@') && email.contains('.') && !email.starts_with('@') && !email.ends_with('.')
}
// Fungsi untuk menjumlahkan dua angka
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_clean_string() {
assert_eq!(clean_string(" Hello World "), "hello world");
assert_eq!(clean_string("RUST"), "rust");
assert_eq!(clean_string(""), "");
}
#[test]
fn test_is_valid_email() {
assert!(is_valid_email("test@example.com"));
assert!(!is_valid_email("invalid-email"));
assert!(!is_valid_email("@domain.com"));
assert!(!is_valid_email("user@.com"));
}
#[test]
fn test_add() {
assert_eq!(add(1, 2), 3);
assert_eq!(add(-1, 1), 0);
}
}
Ini adalah logika inti yang ingin kita gunakan di web dan desktop.
5. Langkah 2: Mengkompilasi Rust ke WebAssembly
Sekarang, kita akan mengkompilasi library Rust core-logic ini menjadi WebAssembly. Kita akan menggunakan tool wasm-pack yang mempermudah proses ini.
Jika belum terinstal, instal wasm-pack:
cargo install wasm-pack
Tambahkan dependensi wasm-bindgen ke Cargo.toml dari proyek core-logic Anda. wasm-bindgen adalah tool yang memungkinkan komunikasi antara JavaScript dan WebAssembly.
# core-logic/Cargo.toml
[package]
name = "core-logic"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib", "rlib"] # Penting untuk WASM
[dependencies]
wasm-bindgen = "0.2"
Kemudian, modifikasi src/lib.rs untuk mengekspos fungsi-fungsi Rust ke JavaScript melalui wasm-bindgen:
// core-logic/src/lib.rs
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn clean_string(input: &str) -> String {
input.trim().to_lowercase()
}
#[wasm_bindgen]
pub fn is_valid_email(email: &str) -> bool {
email.contains('@') && email.contains('.') && !email.starts_with('@') && !email.ends_with('.')
}
#[wasm_bindgen]
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
// ... (bagian #[cfg(test)] mod tests { ... } tetap sama)
📌 Perhatikan atribut #[wasm_bindgen] di atas setiap fungsi yang ingin Anda ekspos.
Sekarang, kompilasi ke WebAssembly:
wasm-pack build --target web
Perintah ini akan membuat folder pkg di dalam core-logic yang berisi file .wasm, file JavaScript glue code, dan package.json. File-file ini siap untuk diimpor di proyek JavaScript/TypeScript.
6. Langkah 3: Mengintegrasikan WASM di Aplikasi Web
Sekarang kita akan membuat aplikasi web sederhana (misalnya dengan Vite) dan mengintegrasikan modul WebAssembly kita.
# Kembali ke root folder proyek Anda, atau di luar core-logic
cd ..
npm create vite@latest web-app -- --template react-ts # atau vue, svelte, dll.
cd web-app
npm install
Salin folder pkg dari core-logic ke dalam web-app/src atau web-app/public atau buat symlink. Untuk kesederhanaan, kita akan menganggap pkg ada di web-app/src/core-logic-pkg.
# Dari root proyek Anda
cp -r core-logic/pkg web-app/src/core-logic-pkg
Sekarang, di web-app/src/App.tsx (jika menggunakan React/Vite), kita bisa mengimpor dan menggunakan fungsi WebAssembly:
// web-app/src/App.tsx
import { useState, useEffect } from 'react';
import init, { clean_string, is_valid_email, add } from './core-logic-pkg/core_logic';
function App() {
const [wasmReady, setWasmReady] = useState(false);
const [emailInput, setEmailInput] = useState('');
const [cleanedString, setCleanedString] = useState('');
const [isValid, setIsValid] = useState(false);
const [num1, setNum1] = useState(0);
const [num2, setNum2] = useState(0);
const [sum, setSum] = useState(0);
useEffect(() => {
init().then(() => {