Rust + Vue Full Stack: Membangun Aplikasi Web Lengkap
Membangun aplikasi web full stack dengan Rust dan Vue adalah kombinasi yang powerful. Rust menawarkan performa tinggi dan keamanan memori di sisi backend, sementara Vue memberikan pengembangan frontend yang cepat dan reaktif. Artikel ini akan membahas cara menghubungkan keduanya menjadi satu aplikasi utuh.
Mengapa Rust + Vue?
Rust dan Vue punya filosofi yang saling melengkapi:
Rust (Backend): Performa C/C++, keamanan memori tanpa garbage collector, type safety yang kuat Vue (Frontend): Reactive UI, ekosistem Vite yang cepat, learning curve yang landai
Kombinasi ini cocok untuk aplikasi yang butuh performa backend tinggi dan UI yang responsif, seperti dashboard, API service, atau aplikasi data-intensive.
Arsitektur Aplikasi
Arsitektur yang kita gunakan terdiri dari tiga layer:
Browser (Vue 3 + Vite)
|
| proxy /api/*
v
Rust Axum Server (localhost:3001)
|
| HTTP request
v
External API / Database
Vite berperan sebagai dev server yang me-proxy request /api/* ke backend Rust. Di production, kamu bisa gunakan reverse proxy seperti Nginx atau Cloudflare.
Membangun Backend dengan Axum
Axum adalah web framework dari ekosistem Tokio yang ringan dan ergonomis. Berikut setup dasarnya.
Cargo.toml:
[package]
name = "my-backend"
version = "0.1.0"
edition = "2021"
[dependencies]
axum = "0.7"
tokio = { version = "1", features = ["full"] }
reqwest = { version = "0.12", features = ["json"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
tower-http = { version = "0.5", features = ["cors"] }
src/main.rs:
use axum::{routing::get, Json, Router};
use tower_http::cors::CorsLayer;
async fn health() -> Json<serde_json::Value> {
Json(serde_json::json!({
"status": "ok"
}))
}
#[tokio::main]
async fn main() {
let app = Router::new()
.route("/api/health", get(health))
.layer(CorsLayer::permissive());
let listener = tokio::net::TcpListener::bind("0.0.0.0:3001")
.await
.unwrap();
println!("Server running on http://localhost:3001");
axum::serve(listener, app).await.unwrap();
}
Beberapa hal penting di sini:
CorsLayer::permissive() mengizinkan request dari domain lain saat development tokio::net::TcpListener adalah async TCP listener dari Tokio axum::serve mengikat listener ke router
Menambahkan Endpoint API
Kita tambahkan endpoint yang mengambil data dari API eksternal dan meneruskannya ke frontend:
use axum::extract::Query;
use axum::http::StatusCode;
use serde::Deserialize;
#[derive(Deserialize)]
struct FilterParams {
tag: Option<String>,
}
async fn list_items(
Query(params): Query<FilterParams>,
) -> Result<Json<serde_json::Value>, StatusCode> {
let mut url = "https://api.example.com/items".to_string();
if let Some(tag) = ¶ms.tag {
url.push_str(&format!("?tag={}", tag));
}
match reqwest::get(&url).await {
Ok(resp) => match resp.json::<serde_json::Value>().await {
Ok(data) => Ok(Json(data)),
Err(_) => Err(StatusCode::BAD_GATEWAY),
},
Err(_) => Err(StatusCode::BAD_GATEWAY),
}
}
Pola ini disebut proxy pattern. Backend Rust menjadi perantara antara frontend dan API eksternal. Keuntungannya:
Bisa menambahkan caching di backend Bisa menyimpan API key secara rahasia Bisa melakukan transformasi data sebelum dikirim ke frontend Bisa menambahkan rate limiting
Daftarkan route-nya:
let app = Router::new()
.route("/api/health", get(health))
.route("/api/items", get(list_items))
.layer(CorsLayer::permissive());
Membangun Frontend dengan Vue 3 + Vite
Buat project Vue dengan Vite:
npm create vite@latest frontend -- --template vue
cd frontend
npm install axios
Konfigurasi Vite agar mem-proxy request API ke backend Rust:
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
server: {
port: 5173,
proxy: {
'/api': {
target: 'http://localhost:3001',
changeOrigin: true,
}
}
}
})
Proxy ini sangat penting. Tanpa proxy, browser akan memblokir request karena CORS policy. Dengan proxy, request dari Vue akan diteruskan ke Rust seolah-olah berasal dari domain yang sama.
Menghubungkan Vue dengan API
Buat komponen Vue yang mengambil data dari backend:
<script setup>
import { ref, onMounted } from 'vue'
import axios from 'axios'
const items = ref([])
const loading = ref(true)
const error = ref(null)
async function fetchItems() {
try {
const { data } = await axios.get('/api/items')
items.value = data
} catch (err) {
error.value = 'Gagal memuat data'
} finally {
loading.value = false
}
}
onMounted(fetchItems)
</script>
<template>
<div v-if="loading">Memuat...</div>
<div v-else-if="error">{{ error }}</div>
<div v-else>
<div v-for="item in items" :key="item.id">
{{ item.nama }}
</div>
</div>
</template>
Axios secara otomatis mengirim request ke /api/items yang akan di-proxy oleh Vite ke http://localhost:3001/api/items.
Alur Data Lengkap
1. User buka http://localhost:5173
2. Vue mounted, panggil axios.get('/api/items')
3. Vite proxy teruskan ke http://localhost:3001/api/items
4. Axum handler terima request
5. Axum fetch data dari API eksternal
6. API eksternal kembalikan JSON
7. Axum teruskan JSON ke Vue
8. Vue render data ke HTML
Setiap langkah di atas berjalan secara async. Tidak ada thread yang diblokir, baik di backend Rust maupun frontend Vue.
Struktur Project Final
my-app/
├── backend/
│ ├── Cargo.toml
│ └── src/
│ └── main.rs
├── frontend/
│ ├── index.html
│ ├── package.json
│ ├── vite.config.js
│ └── src/
│ ├── main.js
│ ├── App.vue
│ └── components/
│ └── ItemList.vue
└── README.md
Menjalankan Aplikasi
Butuh dua terminal:
# Terminal 1 — Backend
cd backend
cargo run
# Terminal 2 — Frontend
cd frontend
npm install
npm run dev
Buka http://localhost:5173 di browser.
Tips Production
Saat deploy ke production, ada beberapa hal yang perlu diperhatikan.
Build frontend:
cd frontend
npm run build
Hasilnya ada di frontend/dist/. Bisa di-serve oleh Nginx, Cloudflare Pages, atau Vercel.
Build backend:
cd backend
cargo build --release
Binary hasil build ada di backend/target/release/. Ukurannya kecil dan tidak butuh runtime tambahan.
Reverse proxy dengan Nginx:
server {
listen 80;
server_name example.com;
location / {
root /var/www/frontend/dist;
try_files $uri /index.html;
}
location /api/ {
proxy_pass http://localhost:3001;
}
}
Atau gunakan Docker untuk mengemas keduanya dalam satu container.
Kesimpulan
Rust dan Vue adalah kombinasi yang solid untuk full stack development. Rust menangani backend dengan performa tinggi dan keamanan memori, sementara Vue menyediakan frontend yang reaktif dan cepat dikembangkan. Proxy di Vite mempermudah integrasi keduanya selama development.
Project buku-doa adalah contoh nyata dari arsitektur ini. Backend Rust memproxy API publik, frontend Vue menampilkannya dengan UI yang bersih. Kamu bisa mengembangkan pola ini untuk berbagai jenis aplikasi.
Repository contoh: github.com/erlk1m/buku-doa
~Erlkim
Artikel Terkait

Belajar Rust dari Nol: Panduan Lengkap untuk Pemula
Panduan lengkap belajar Rust dari nol.

Collections, Iterators, dan Closures di Rust: Panduan Praktis
Menguasai collections, iterators, dan closures di Rust. Vec, HashMap, String, dan cara memproses data dengan efisien dan elegan.

Concurrency dan Async Programming di Rust: Panduan Lengkap
Belajar concurrency dan async programming di Rust. Thread, mutex, channel, dan async/await untuk kode yang cepat dan aman.
Komentar