tauri-v2

安装量: 2.5K
排名: #807

安装

npx skills add https://github.com/nodnarbnitram/claude-code-extensions --skill tauri-v2

Tauri v2 Development Skill

Build cross-platform desktop and mobile apps with web frontends and Rust backends.

Before You Start

This skill prevents 8+ common errors and saves ~60% tokens.

Metric Without Skill With Skill Setup Time ~2 hours ~30 min Common Errors 8+ 0 Token Usage High (exploration) Low (direct patterns) Known Issues This Skill Prevents Permission denied errors from missing capabilities IPC failures from unregistered commands in generate_handler! State management panics from type mismatches Mobile build failures from missing Rust targets White screen issues from misconfigured dev URLs Quick Start Step 1: Create a Tauri Command // src-tauri/src/lib.rs

[tauri::command]

fn greet(name: String) -> String { format!("Hello, {}!", name) }

pub fn run() { tauri::Builder::default() .invoke_handler(tauri::generate_handler![greet]) .run(tauri::generate_context!()) .expect("error while running tauri application"); }

Why this matters: Commands not in generate_handler![] silently fail when invoked from frontend.

Step 2: Call from Frontend import { invoke } from '@tauri-apps/api/core';

const greeting = await invoke('greet', { name: 'World' }); console.log(greeting); // "Hello, World!"

Why this matters: Use @tauri-apps/api/core (not @tauri-apps/api/tauri - that's v1 API).

Step 3: Add Required Permissions // src-tauri/capabilities/default.json { "$schema": "../gen/schemas/desktop-schema.json", "identifier": "default", "windows": ["main"], "permissions": ["core:default"] }

Why this matters: Tauri v2 denies everything by default - explicit permissions required for all operations.

Critical Rules Always Do Register every command in tauri::generate_handler![cmd1, cmd2, ...] Return Result from commands for proper error handling Use Mutex for shared state accessed from multiple commands Add capabilities before using any plugin features Use lib.rs for shared code (required for mobile builds) Never Do Never use borrowed types (&str) in async commands - use owned types Never block the main thread - use async for I/O operations Never hardcode paths - use Tauri path APIs (app.path()) Never skip capability setup - even "safe" operations need permissions Common Mistakes

Wrong - Borrowed type in async:

[tauri::command]

async fn bad(name: &str) -> String { // Compile error! name.to_string() }

Correct - Owned type:

[tauri::command]

async fn good(name: String) -> String { name }

Why: Async commands cannot borrow data across await points; Tauri requires owned types for async command parameters.

Known Issues Prevention Issue Root Cause Solution "Command not found" Missing from generate_handler! Add command to handler macro "Permission denied" Missing capability Add to capabilities/default.json State panic on access Type mismatch in State Use exact type from .manage() White screen on launch Frontend not building Check beforeDevCommand in config IPC timeout Blocking async command Remove blocking code or use spawn Mobile build fails Missing Rust targets Run rustup target add Configuration Reference tauri.conf.json { "$schema": "./gen/schemas/desktop-schema.json", "productName": "my-app", "version": "1.0.0", "identifier": "com.example.myapp", "build": { "devUrl": "http://localhost:5173", "frontendDist": "../dist", "beforeDevCommand": "npm run dev", "beforeBuildCommand": "npm run build" }, "app": { "windows": [{ "label": "main", "title": "My App", "width": 800, "height": 600 }], "security": { "csp": "default-src 'self'; img-src 'self' data:", "capabilities": ["default"] } }, "bundle": { "active": true, "targets": "all", "icon": ["icons/icon.icns", "icons/icon.ico", "icons/icon.png"] } }

Key settings:

build.devUrl: Must match your frontend dev server port app.security.capabilities: Array of capability file identifiers Cargo.toml [ package ] name = "app" version = "0.1.0" edition = "2021"

[ lib ] name = "app_lib" crate-type = ["staticlib", "cdylib", "rlib"]

[ build-dependencies ] tauri-build = { version = "2", features = [] }

[ dependencies ] tauri = { version = "2", features = [] } serde = { version = "1", features = ["derive"] } serde_json = "1"

Key settings:

[lib] section: Required for mobile builds crate-type: Must include all three types for cross-platform Common Patterns Error Handling Pattern use thiserror::Error;

[derive(Debug, Error)]

enum AppError { #[error("IO error: {0}")] Io(#[from] std::io::Error), #[error("Not found: {0}")] NotFound(String), }

impl serde::Serialize for AppError { fn serialize(&self, serializer: S) -> Result where S: serde::ser::Serializer { serializer.serialize_str(self.to_string().as_ref()) } }

[tauri::command]

fn risky_operation() -> Result { Ok("success".into()) }

State Management Pattern use std::sync::Mutex; use tauri::State;

struct AppState { counter: u32, }

[tauri::command]

fn increment(state: State<'_, Mutex>) -> u32 { let mut s = state.lock().unwrap(); s.counter += 1; s.counter }

// In builder: tauri::Builder::default() .manage(Mutex::new(AppState { counter: 0 }))

Event Emission Pattern use tauri::Emitter;

[tauri::command]

fn start_task(app: tauri::AppHandle) { std::thread::spawn(move || { app.emit("task-progress", 50).unwrap(); app.emit("task-complete", "done").unwrap(); }); }

import { listen } from '@tauri-apps/api/event';

const unlisten = await listen('task-progress', (e) => { console.log('Progress:', e.payload); }); // Call unlisten() when done

Channel Streaming Pattern use tauri::ipc::Channel;

[derive(Clone, serde::Serialize)]

[serde(tag = "event", content = "data")]

enum DownloadEvent { Progress { percent: u32 }, Complete { path: String }, }

[tauri::command]

async fn download(url: String, on_event: Channel) { for i in 0..=100 { on_event.send(DownloadEvent::Progress { percent: i }).unwrap(); } on_event.send(DownloadEvent::Complete { path: "/downloads/file".into() }).unwrap(); }

import { invoke, Channel } from '@tauri-apps/api/core';

const channel = new Channel(); channel.onmessage = (msg) => console.log(msg.event, msg.data); await invoke('download', { url: 'https://...', onEvent: channel });

Bundled Resources References

Located in references/:

capabilities-reference.md - Permission patterns and examples ipc-patterns.md - Complete IPC examples

Note: For deep dives on specific topics, see the reference files above.

Dependencies Required Package Version Purpose @tauri-apps/cli ^2.0.0 CLI tooling @tauri-apps/api ^2.0.0 Frontend APIs tauri ^2.0.0 Rust core tauri-build ^2.0.0 Build scripts Optional (Plugins) Package Version Purpose tauri-plugin-fs ^2.0.0 File system access tauri-plugin-dialog ^2.0.0 Native dialogs tauri-plugin-shell ^2.0.0 Shell commands, open URLs tauri-plugin-http ^2.0.0 HTTP client tauri-plugin-store ^2.0.0 Key-value storage Official Documentation Tauri v2 Documentation Commands Reference Capabilities & Permissions Configuration Reference Troubleshooting White Screen on Launch

Symptoms: App launches but shows blank white screen

Solution:

Verify devUrl matches your frontend dev server port Check beforeDevCommand runs your dev server Open DevTools (Cmd+Option+I / Ctrl+Shift+I) to check for errors Command Returns Undefined

Symptoms: invoke() returns undefined instead of expected value

Solution:

Verify command is in generate_handler![] Check Rust command actually returns a value Ensure argument names match (camelCase in JS, snake_case in Rust by default) Mobile Build Failures

Symptoms: Android/iOS build fails with missing target

Solution:

Android targets

rustup target add aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android

iOS targets (macOS only)

rustup target add aarch64-apple-ios x86_64-apple-ios aarch64-apple-ios-sim

Setup Checklist

Before using this skill, verify:

npx tauri info shows correct Tauri v2 versions src-tauri/capabilities/default.json exists with at least core:default All commands registered in generate_handler![] lib.rs contains shared code (for mobile support) Required Rust targets installed for target platforms

返回排行榜