@tauri-apps/api 包
这是 Tauri 官方提供的前端 JavaScript/TypeScript 库,封装了所有与 Rust 后端通信的 API:
# 安装(项目创建时通常已自动安装)
npm install @tauri-apps/api
# 各功能插件(按需安装)
npm install @tauri-apps/plugin-fs
npm install @tauri-apps/plugin-dialog
npm install @tauri-apps/plugin-notification
npm install @tauri-apps/plugin-store
npm install @tauri-apps/plugin-http
React + Vite 集成
vite.config.ts 配置
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
// Tauri 要求:防止 Vite 清除 Rust 错误
clearScreen: false,
server: {
port: 1420, // 与 tauri.conf.json devUrl 保持一致
strictPort: true, // 端口被占用时报错而非自动换端口
host: false, // 不对外暴露,仅本机访问
hmr: {
protocol: 'ws',
host: 'localhost',
port: 1420,
},
watch: {
// 监听 Rust 文件变化(触发 Tauri 重新编译)
ignored: ['**/src-tauri/**'],
},
},
envPrefix: ['VITE_', 'TAURI_'], // 允许 TAURI_ 开头的环境变量
build: {
// Windows 上 Tauri 使用 Chromium,支持现代特性
target: process.env.TAURI_ENV_PLATFORM === 'windows'
? 'chrome105'
: 'safari13',
minify: !process.env.TAURI_ENV_DEBUG ? 'esbuild' : false,
sourcemap: !!process.env.TAURI_ENV_DEBUG,
},
});
React 组件中调用 Tauri
import { useState } from 'react';
import { invoke } from '@tauri-apps/api/core';
function App() {
const [message, setMessage] = useState('');
const [name, setName] = useState('World');
async function handleGreet() {
// invoke 调用 Rust 中的 #[tauri::command] 函数
const result = await invoke<string>('greet', { name });
setMessage(result);
}
return (
<div>
<input
value={name}
onChange={e => setName(e.target.value)}
placeholder="Enter your name"
/>
<button onClick={handleGreet}>Greet</button>
<p>{message}</p>
</div>
);
}
Vue 3 + Vite 集成
<!-- src/App.vue -->
<script setup lang="ts">
import { ref } from 'vue';
import { invoke } from '@tauri-apps/api/core';
const name = ref('World');
const message = ref('');
async function greet() {
message.value = await invoke<string>('greet', { name: name.value });
}
</script>
<template>
<div>
<input v-model="name" placeholder="Enter your name" />
<button @click="greet">Greet</button>
<p>{{ message }}</p>
</div>
</template>
SvelteKit 集成
SvelteKit 是 SSR 框架,在 Tauri 中需要禁用 SSR,使用纯客户端模式:
// svelte.config.js
import adapter from '@sveltejs/adapter-static';
export default {
kit: {
adapter: adapter(),
prerender: {
handleMissingID: 'ignore',
},
},
};
<!-- src/routes/+layout.ts -->
// 禁用 SSR,使用纯 SPA 模式
export const ssr = false;
export const prerender = true;
<!-- src/routes/+page.svelte -->
<script lang="ts">
import { invoke } from '@tauri-apps/api/core';
let message = '';
let name = 'World';
async function greet() {
message = await invoke<string>('greet', { name });
}
</script>
<input bind:value={name} />
<button on:click={greet}>Greet</button>
<p>{message}</p>
检测 Tauri 运行环境
同一份前端代码可能在浏览器和 Tauri 两种环境中运行。区分环境的常见方式:
import { isTauri } from '@tauri-apps/api/core';
// 方式1:官方 API(推荐)
if (isTauri()) {
console.log('Running in Tauri');
} else {
console.log('Running in browser');
}
// 方式2:检查 window.__TAURI__ 全局对象
const isTauriEnv = ('__TAURI__' in window);
// 方式3:Vite 环境变量(构建时替换)
// tauri dev/build 会设置 TAURI_ENV_PLATFORM
const platform = import.meta.env.TAURI_ENV_PLATFORM; // "macos" | "windows" | "linux"
const isDesktop = !!import.meta.env.TAURI_ENV_PLATFORM;
WebView 的限制与注意事项
require()、fs、path 等 Node.js 模块。需要系统功能必须通过 Tauri Commands 调用 Rust 实现。tauri://localhost 协议加载,向外部 API 发起请求受 CORS 限制。需要在 tauri.conf.json 配置 CSP,或使用 plugin-http 绕过限制。localStorage 和 sessionStorage 可正常使用,数据存储在 Tauri 应用的 Web 数据目录中。跨版本持久化建议使用 plugin-store。TypeScript 类型支持
// tsconfig.json 推荐配置
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true,
"skipLibCheck": true,
"types": ["@tauri-apps/api"] // 引入 Tauri 类型声明
}
}
// 为 invoke 返回值定义接口提供类型安全
interface SystemInfo {
os: string;
arch: string;
version: string;
}
// 使用泛型参数指定返回类型
const info = await invoke<SystemInfo>('get_system_info');
console.log(info.os); // TypeScript 知道这是 string
// 传参类型安全
interface ReadFileArgs {
path: string;
encoding?: string;
}
const content = await invoke<string>('read_file', {
path: '/tmp/test.txt',
encoding: 'utf-8',
} satisfies ReadFileArgs);
specta 是一个 Rust 库,可以从 Rust 结构体自动生成对应的 TypeScript 类型定义,配合 tauri-specta 插件还能自动生成类型安全的 invoke 封装函数。这样修改 Rust 结构体后,TypeScript 类型会自动同步更新,避免手动维护类型定义。
使用 plugin-store 持久化数据
相比 localStorage,plugin-store 提供了更可靠的持久化存储,数据存储在应用数据目录中,支持类型安全访问:
npm install @tauri-apps/plugin-store
import { load } from '@tauri-apps/plugin-store';
// 打开(或创建)一个 store 文件
// 文件存储在 appDataDir() 下的 settings.json
const store = await load('settings.json', { autoSave: true });
// 写入值
await store.set('theme', 'dark');
await store.set('fontSize', 16);
await store.set('recentFiles', ['/path/to/file1.txt', '/path/to/file2.txt']);
// 读取值(带默认值)
const theme = ((await store.get('theme')) ?? 'light') as string;
const fontSize = ((await store.get('fontSize')) ?? 14) as number;
// 手动保存(autoSave: false 时需要)
await store.save();
// 删除某个键
await store.delete('oldKey');
// 检查某个键是否存在
const hasTheme = await store.has('theme');
// capabilities/default.json — 需要添加 store 权限
{
"permissions": [
"store:allow-load",
"store:allow-set",
"store:allow-get",
"store:allow-delete",
"store:allow-save"
]
}
plugin-http:绕过 CORS 限制
Tauri 应用在生产模式下前端使用 tauri:// 协议,向外部 HTTP API 发请求时会遇到 CORS 问题。plugin-http 通过 Rust 层发起请求,完全绕过浏览器的跨域限制:
npm install @tauri-apps/plugin-http
import { fetch } from '@tauri-apps/plugin-http';
// 使用方式与 Web 标准 fetch API 完全相同
const response = await fetch('https://api.github.com/repos/tauri-apps/tauri', {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json',
},
});
const data = await response.json();
console.log(data.stargazers_count);
// POST 请求
const result = await fetch('https://api.example.com/data', {
method: 'POST',
body: JSON.stringify({ key: 'value' }),
headers: { 'Content-Type': 'application/json' },
});
// capabilities/default.json
{
"permissions": [
"http:default" // 允许发起 HTTP 请求
]
}
plugin-http 默认允许请求任意 URL。出于安全考虑,可以在 capabilities 中配置 http:scope 限制只能访问特定域名:{"identifier": "http:scope", "allow": ["https://api.example.com/**"]}。这可以防止恶意代码通过注入攻击访问内网服务。
tauri-specta:自动生成类型安全绑定
手动维护 TypeScript 接口与 Rust 结构体的同步非常繁琐,tauri-specta 可以从 Rust 代码自动生成 TypeScript 类型定义和类型安全的调用函数:
// Cargo.toml
// specta = { version = "2", features = ["derive"] }
// tauri-specta = { version = "2", features = ["derive", "typescript"] }
use specta::Type;
use tauri_specta::{collect_commands, ts};
// 为结构体派生 Type 和 serde::Serialize/Deserialize
#[derive(Debug, serde::Serialize, serde::Deserialize, Type)]
pub struct SystemInfo {
pub os: String,
pub arch: String,
pub cpu_count: u32,
pub total_memory: u64,
}
#[tauri::command]
#[specta::specta] // 标记此 command 用于类型导出
fn get_system_info() -> SystemInfo {
SystemInfo {
os: std::env::consts::OS.to_string(),
arch: std::env::consts::ARCH.to_string(),
cpu_count: num_cpus::get() as u32,
total_memory: 0,
}
}
fn main() {
// 生成 bindings.ts 文件(开发时运行一次)
#[cfg(debug_assertions)]
ts::export(collect_commands![get_system_info], "../src/bindings.ts")
.unwrap();
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![get_system_info])
.run(tauri::generate_context!())
.unwrap();
}
// 自动生成的 src/bindings.ts(不要手动修改)
export type SystemInfo = {
os: string;
arch: string;
cpuCount: number; // Rust 的 snake_case 自动转为 camelCase
totalMemory: number;
};
// 类型安全的封装函数(参数和返回类型都有 TypeScript 类型)
export function getSystemInfo() {
return invoke<SystemInfo>('get_system_info');
}
// 使用:直接调用封装函数,自动类型推断
const info = await getSystemInfo();
console.log(info.cpuCount); // TypeScript 知道这是 number
环境变量与构建配置
Tauri 在构建时会注入一系列环境变量,前端代码可以通过 import.meta.env 访问:
"windows"、"macos"、"linux"、"ios"、"android"。"x86"、"x86_64"、"aarch64"。"unix"(macOS/Linux)或 "windows"。"true" 或 "false"。// vite.config.ts 中启用 TAURI_ 环境变量前缀
envPrefix: ['VITE_', 'TAURI_'],
// 前端代码中使用
const platform = import.meta.env.TAURI_ENV_PLATFORM;
// 平台特定功能
function getKeyboardShortcut(action: string) {
const isMac = import.meta.env.TAURI_ENV_PLATFORM === 'macos';
const modifier = isMac ? '⌘' : 'Ctrl';
switch (action) {
case 'save': return `${modifier}+S`;
case 'open': return `${modifier}+O`;
default: return action;
}
}
本章小结
- @tauri-apps/api 是前端入口:提供 invoke(Commands)、emit/listen(Events)、path(路径 API)等核心功能;各功能插件(plugin-fs/dialog/store 等)按需安装。
- Vite 配置关键点:clearScreen: false(保留 Rust 错误输出)、strictPort: true(避免端口冲突)、envPrefix 包含 TAURI_(暴露构建环境变量);build.target 根据平台选择 chrome105 或 safari13。
- 框架集成差异:React/Vue 直接使用 Vite;SvelteKit 需要 adapter-static 和 ssr: false 以禁用服务端渲染;Angular/Solid 同理需要纯 SPA 模式。
- isTauri() 检测运行环境:同一套代码可在浏览器调试,也可在 Tauri 中运行;用 isTauri() 或 window.__TAURI__ 区分,在浏览器环境下 gracefully fallback。
- plugin-store 比 localStorage 更可靠:数据存在 appDataDir(),支持 autoSave;适合应用配置、用户偏好等需要持久化的结构化数据。
- plugin-http 绕过 CORS:通过 Rust 层发送 HTTP 请求,完全兼容 Web fetch API;生产环境建议配置 http:scope 限制可访问域名。
- tauri-specta 自动同步类型:从 Rust 结构体自动生成 TypeScript 类型定义,避免手动维护双端类型;适合中大型项目。