integrating-tauri-rust-frontends について
Rust/WASM フロントエンドを Tauri v2 に統合する開発者向けのガイドです。4つのフレームワーク、Trunk の設定、Tauri API の利用、モバイル開発を扱います。
主な機能
- 01Leptos、Yew、Dioxus、Sycamore に対応
- 02Trunk によるビルドと開発サーバー
- 03Tauri と WASM API の設定
- 04モバイルのホットリロード設定
- 05ビルド時のトラブルシューティング
活用シーン
- 01Rust/WASM デスクトップアプリの構築
- 02Tauri 用 SPA または SSG の設定
- 03モバイル開発のホットリロード設定
- 04WASM の読み込みやビルドの問題解決
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ dchuk/ claude-code-tauri-skills --skill integrating-tauri-rust-frontendsインストール後、Claude Code で/integrating-tauri-rust-frontendsを入力して読み込まれたか確認します。
詳細
Tauri Rust/WASM フロントエンド統合
このスキルでは、WASM を使用してデスクトップアプリやモバイルアプリを構築するために、Rust ベースのフロントエンドフレームワークを Tauri v2 と統合する方法について説明します。
対応フレームワーク
| フレームワーク | 説明 | バンドラー |
|---|---|---|
| Leptos | Web UI を構築するリアクティブな Rust フレームワーク | Trunk |
| Yew | コンポーネントベースの Rust フレームワーク | Trunk |
| Dioxus | クロスプラットフォーム UI フレームワーク | Trunk |
| Sycamore | Rust 向けのリアクティブライブラリ | Trunk |
すべての Rust/WASM フロントエンドでは、バンドラー兼開発サーバーとして Trunk を使用します。
重要な要件
- 静的サイト生成(SSG)のみ - Tauri はサーバーベースのソリューション(SSR)をサポートしていません。SSG、SPA、または MPA のアプローチを使用してください。
- withGlobalTauri - WASM フロントエンドから
window.__TAURI__とwasm-bindgenを介して Tauri API にアクセスするには、有効にする必要があります。 - WebSocket プロトコル - モバイル開発でのホットリロードには、
ws_protocol = "ws"を設定してください。
プロジェクト構成
my-tauri-app/
├── src/
│ ├── main.rs # Rust frontend entry point
│ └── app.rs # Application component
├── src-tauri/
│ ├── src/
│ │ └── main.rs # Tauri backend
│ ├── Cargo.toml # Tauri dependencies
│ └── tauri.conf.json # Tauri configuration
├── index.html # HTML entry point for Trunk
├── Cargo.toml # Frontend dependencies
├── Trunk.toml # Trunk bundler configuration
└── dist/ # Build output (generated)
設定ファイル
Tauri の設定(src-tauri/tauri.conf.json)
{
"build": {
"beforeDevCommand": "trunk serve",
"devUrl": "http://localhost:1420",
"beforeBuildCommand": "trunk build",
"frontendDist": "../dist"
},
"app": {
"withGlobalTauri": true
}
}
主な設定項目:
beforeDevCommand:Tauri の起動前に Trunk 開発サーバーを実行しますdevUrl:Trunk がフロントエンドを提供する URL(既定値:Leptos では 1420、通常の Trunk では 8080)beforeBuildCommand:パッケージ化の前に WASM バンドルをビルドしますfrontendDist:ビルド済みフロントエンドアセットのパスwithGlobalTauri:WASM には必須 - API アクセス用にwindow.__TAURI__を公開します
Trunk の設定(Trunk.toml)
[build]
target = "./index.html"
dist = "./dist"
[watch]
ignore = ["./src-tauri"]
[serve]
port = 1420
open = false
[serve.ws]
ws_protocol = "ws"
主な設定項目:
target:Trunk ディレクティブを含む HTML エントリーポイントignore:Tauri バックエンドの変更が監視されないようにしますport:tauri.conf.json のdevUrlと一致させる必要がありますopen = false:ブラウザーの自動起動を防ぎます(表示は Tauri が処理します)ws_protocol = "ws":モバイルでのホットリロードに必須です
フロントエンドの Cargo.toml(ルート)
[package]
name = "my-app-frontend"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib", "rlib"]
[dependencies]
# Core WASM dependencies
wasm-bindgen = "0.2"
wasm-bindgen-futures = "0.4"
js-sys = "0.3"
web-sys = { version = "0.3", features = ["Window", "Document"] }
# Tauri API bindings for WASM
tauri-wasm = { version = "2", features = ["all"] }
# Choose your framework:
# For Leptos:
leptos = { version = "0.6", features = ["csr"] }
# For Yew:
# yew = { version = "0.21", features = ["csr"] }
# For Dioxus:
# dioxus = { version = "0.5", features = ["web"] }
[profile.release]
opt-level = "z"
lto = true
codegen-units = 1
panic = "abort"
主な設定項目:
crate-type = ["cdylib", "rlib"]:WASM のコンパイルに必須ですtauri-wasm:Tauri API への Rust バインディングを提供しますfeatures = ["csr"]:フレームワークのクライアントサイドレンダリングを指定します- リリースプロファイルは、WASM バイナリサイズを小さくするよう最適化されています
HTML エントリーポイント(index.html)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>My Tauri App</title>
<link data-trunk rel="css" href="styles.css" />
</head>
<body>
<div id="app"></div>
<link data-trunk rel="rust" href="." data-wasm-opt="z" />
</body>
</html>
Trunk ディレクティブ:
data-trunk rel="css":CSS ファイルを含めますdata-trunk rel="rust":Rust クレートを WASM にコンパイルしますdata-wasm-opt="z":サイズを最適化します
Leptos のセットアップ
Leptos 専用 Cargo.toml
[package]
name = "my-leptos-app"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib", "rlib"]
[dependencies]
leptos = { version = "0.6", features = ["csr"] }
wasm-bindgen = "0.2"
wasm-bindgen-futures = "0.4"
console_error_panic_hook = "0.1"
tauri-wasm = { version = "2", features = ["all"] }
[profile.release]
opt-level = "z"
lto = true
Leptos のメインエントリー(src/main.rs)
use leptos::*;
mod app;
use app::App;
fn main() {
console_error_panic_hook::set_once();
mount_to_body(|| view! { <App /> });
}
Leptos の App コンポーネント(src/app.rs)
use leptos::*;
use wasm_bindgen::prelude::*;
use wasm_bindgen_futures::spawn_local;
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_namespace = ["window", "__TAURI__", "core"])]
async fn invoke(cmd: &str, args: JsValue) -> JsValue;
}
#[component]
pub fn App() -> impl IntoView {
let (message, set_message) = create_signal(String::new());
let greet = move |_| {
spawn_local(async move {
let args = serde_json::json!({ "name": "World" });
let args_js = serde_wasm_bindgen::to_value(&args).unwrap();
let result = invoke("greet", args_js).await;
let greeting: String = serde_wasm_bindgen::from_value(result).unwrap();
set_message.set(greeting);
});
};
view! {
<main>
<h1>"Welcome to Tauri + Leptos"</h1>
<button on:click=greet>"Greet"</button>
<p>{message}</p>
</main>
}
}
別の方法:tauri-wasm クレートを使用する
use leptos::*;
use tauri_wasm::api::core::invoke;
#[component]
pub fn App() -> impl IntoView {
let (message, set_message) = create_signal(String::new());
let greet = move |_| {
spawn_local(async move {
let result: String = invoke("greet", &serde_json::json!({ "name": "World" }))
.await
.unwrap();
set_message.set(result);
});
};
view! {
<main>
<button on:click=greet>"Greet"</button>
<p>{message}</p>
</main>
}
}
Tauri バックエンドコマンド
src-tauri/src/main.rs 内:
#[tauri::command]
fn greet(name: &str) -> String {
format!("Hello, {}! You've been greeted from Rust!", name)
}
fn main() {
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![greet])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
開発コマンド
# Install Trunk
cargo install trunk
# Add WASM target
rustup target add wasm32-unknown-unknown
# Development (runs Trunk + Tauri)
cd src-tauri && cargo tauri dev
# Build for production
cd src-tauri && cargo tauri build
# Trunk only (for frontend debugging)
trunk serve --port 1420
# Build WASM only
trunk build --release
モバイル開発
モバイルプラットフォームでは、追加の設定が必要です。
モバイル向け Trunk.toml
[serve]
port = 1420
open = false
address = "0.0.0.0" # Listen on all interfaces for mobile
[serve.ws]
ws_protocol = "ws" # Required for mobile hot-reload
モバイル向け tauri.conf.json
{
"build": {
"beforeDevCommand": "trunk serve --address 0.0.0.0",
"devUrl": "http://YOUR_LOCAL_IP:1420"
}
}
YOUR_LOCAL_IP を、お使いのマシンのローカル IP(例:192.168.1.100)に置き換えてください。
WASM から Tauri API にアクセスする
方法 1:wasm-bindgen を直接使用する(制御性を重視する場合に推奨)
use wasm_bindgen::prelude::*;
use serde::{Serialize, Deserialize};
#[wasm_bindgen]
extern "C" {
// Core invoke
#[wasm_bindgen(js_namespace = ["window", "__TAURI__", "core"], catch)]
async fn invoke(cmd: &str, args: JsValue) -> Result<JsValue, JsValue>;
// Event system
#[wasm_bindgen(js_namespace = ["window", "__TAURI__", "event"])]
async fn listen(event: &str, handler: &Closure<dyn Fn(JsValue)>) -> JsValue;
#[wasm_bindgen(js_namespace = ["window", "__TAURI__", "event"])]
async fn emit(event: &str, payload: JsValue);
}
// Usage
async fn call_backend() -> Result<String, String> {
let args = serde_wasm_bindgen::to_value(&serde_json::json!({
"path": "/some/path"
})).map_err(|e| e.to_string())?;
let result = invoke("read_file", args)
.await
.map_err(|e| format!("{:?}", e))?;
serde_wasm_bindgen::from_value(result)
.map_err(|e| e.to_string())
}
方法 2:tauri-wasm クレートを使用する
use tauri_wasm::api::{core, event, dialog, fs};
// Invoke command
let result: MyResponse = core::invoke("my_command", &my_args).await?;
// Listen to events
event::listen("my-event", |payload| {
// Handle event
}).await;
// Emit events
event::emit("my-event", &payload).await;
// File dialogs
let file = dialog::open(dialog::OpenDialogOptions::default()).await?;
// File system (requires permissions)
let contents = fs::read_text_file("path/to/file").await?;
トラブルシューティング
WASM が読み込まれない
- tauri.conf.json で
withGlobalTauri: trueが設定されていることを確認してください - ブラウザーのコンソールで WASM エラーを確認してください
wasm32-unknown-unknownターゲットがインストールされていることを確認してください
モバイルでホットリロードが機能しない
- Trunk.toml で
ws_protocol = "ws"を設定してください - モバイルからアクセスできるよう、
address = "0.0.0.0"を使用してください - ファイアウォールで開発ポートへの接続が許可されていることを確認してください
Tauri API が未定義
withGlobalTauriはtrueにする必要があります- ブラウザーのコンソールで
window.__TAURI__が存在することを確認してください - tauri-wasm のバージョンが Tauri のバージョンと一致していることを確認してください
WASM バイナリのサイズが大きい
- リリースプロファイルの最適化を有効にしてください
- サイズ最適化に
opt-level = "z"を使用してください lto = trueで LTO を有効にしてくださいwasm-optによる後処理を検討してください
Trunk のビルドに失敗する
- Cargo.toml に
crate-type = ["cdylib", "rlib"]が含まれていることを確認してください - index.html に正しい
data-trunkディレクティブがあることを確認してください - フレームワークでサーバーサイド機能が有効になっていないことを確認してください
バージョン互換性
| コンポーネント | バージョン |
|---|---|
| Tauri | 2.x |
| Trunk | 0.17+ |
| Leptos | 0.6+ |
| wasm-bindgen | 0.2.x |
| tauri-wasm | 2.x |
tauri-wasm のバージョンは、必ず Tauri のバージョンに合わせてください。
コメント
Markdown 対応