Tauri(十八)——如何开发 Tauri 插件

前言

Tauri 项目也做了一段时间了,也有用别人开发的插件。自己也想知道如何开发 Tauri 插件。

Tauri 插件介绍

插件可以挂载到 Tauri 的生命周期中暴露需求 webview API 的 Rust 代码,使用 Rust、Kotlin 或 Swift 代码处理命令并能处理更多需求。

Tauri 提供了一个基于 webview 功能的视窗系统,一个在 Rust 进程和 webview 之间发送信息的方式,一个事件系统,以及一些增强开发体验的工具。 设计上 Tauri Core 只包含所有人都需要的功能。相对地,它提供了一种将外部功能添加到 Tauri 应用程序中的机制,被称为插件。

一个 Tauri 插件由一个 Cargo 包和一个可选的 NPM 包(用于提供命令和事件 API 绑定)构成

何时需要开发 Tauri 插件?

  1. 需要访问系统原生 API(文件、硬件、网络底层)
  2. 性能关键型任务(大数据处理、实时计算)
  3. 代码复用与团队协作(跨项目共享功能模块)
  4. 安全敏感场景(加密、认证、许可证管理)

通过 Tauri 插件,开发者可以 兼顾 Web 的开发效率与 Native 的性能能力,构建真正高性能、跨平台的桌面应用。

Tauri 插件核心概念

插件作用:封装可复用的跨平台功能模块(如硬件访问、加密算法),通过 Rust 后端 + 前端 API 暴露能力。

技术栈

  • Rust:核心逻辑实现
  • TypeScript/JavaScript:前端 API 接口
  • WASM(可选):浏览器端直接调用

创建基础插件模板

1. 命名规范

Tauri 插件具有一个前缀(Rust 包使用 tauri-plugin- 前缀,NPM 包使用 @tauri-apps/plugin- 前缀),随后是插件名称。 插件名称由插件配置中的 tauri.conf.json > plugin 和许可列表中的配置确定。

默认情况下,Tauri 会在你的插件 crate 前面加上 tauri-plugin-。这有助于你的插件被 Tauri 社区发现,但不是必须的。初始化新插件项目时,必须提供其名称。生成包名称将为 tauri-plugin-{plugin-name},JavaScript NPM 包名称为 tauri-plugin-{plugin-name}-api(尽管我们建议使用 NPM 范围如果可能的话)。NPM 包的 Tauri 命名约定是 @scope-name/plugin-{plugin-name}

2. 初始化 Rust 插件库

使用引导创建一个新的插件项目,请运行 plugin new。如果不需要相应的 NPM 程序包,请使用 --no-api 命令行标志。

bash 复制代码
pnpm tauri plugin new [name]

cargo new tauri-plugin-example --lib
cd tauri-plugin-example

这会在 tauri-plugin-[name] 目录下初始化插件,取决于初始化插件时所选择的命令行标志,项目将具有以下结构:

css 复制代码
. tauri-plugin-[name]/
├── src/                - Rust 代码
│ ├── commands.rs       - 定义 webview 可用的命令
| ├── desktop.rs        - 桌面实现
| ├── error.rs          - 用于返回 results 的默认的错误类型
│ ├── lib.rs            - 重新导出适当的实现、设置状态......
│ ├── mobile.rs         - 移动端实现
│ └── models.rs         - 公共的结构体
├── permissions/        - 这将托管(生成的)命令的权限文件
├── android             - 安卓库
├── ios                 - Swift 包
├── guest-js            - JavaScript API 绑定的源代码
├── dist-js             - 从 guest-js 转译的资源
├── Cargo.toml          - Cargo 包元数据
└── package.json        - NPM 包元数据

3. 编辑 Cargo.toml

toml 复制代码
[package]
name = "tauri-plugin-example"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["cdylib"]  # 编译为动态库

[dependencies]
tauri = { version = "2.0", features = ["plugin"] }
serde = { version = "1.0", features = ["derive"] }  # 序列化支持

4. 实现插件结构

rust 复制代码
// src/lib.rs
use tauri::{
  plugin::{Builder, TauriPlugin},
  Runtime, AppHandle,
};

// 定义插件配置(可选)
#[derive(serde::Deserialize)]
pub struct Config {
  api_key: String,
}

// 核心插件实现
pub fn init<R: Runtime>() -> TauriPlugin<R, Config> {
  Builder::new("example")
    .setup(|app, config| {
      println!("插件初始化,配置密钥: {}", config.api_key);
      Ok(())
    })
    .invoke_handler(|app, invoke| {
      // 处理前端调用
    })
    .build()
}

5. 生命周期事件

插件可以挂载到如下生命周期事件中:

实现前后端通信

1. 定义 Rust 命令

rust 复制代码
// 添加命令处理
#[tauri::command]
fn greet(name: &str) -> String {
  format!("Hello, {}!", name)
}

// 更新插件初始化
pub fn init<R: Runtime>() -> TauriPlugin<R, Config> {
  Builder::new("example")
    .setup(|app, config| { /* ... */ })
    .invoke_handler(tauri::generate_handler![greet])  // 注册命令
    .build()
}

2. 前端调用插件

typescript 复制代码
// 前端集成 (JavaScript/TypeScript)
import { invoke } from "@tauri-apps/api";

async function callPlugin() {
  const response = await invoke("plugin:example|greet", { name: "World" });
  console.log(response); // 输出 "Hello, World!"
}

高级功能扩展

1. 事件系统

rust 复制代码
// Rust 端触发事件
app.emit_all("plugin-event", "数据载荷").unwrap();

// 前端监听
import { listen } from "@tauri-apps/api/event";
listen("plugin-event", (event) => {
  console.log("收到事件:", event.payload);
});

2. 状态管理

rust 复制代码
// 定义共享状态
struct AppState {
  counter: Mutex<i32>,
}

// 注册状态
app.manage(AppState { counter: Mutex::new(0) });

// 在命令中使用状态
#[tauri::command]
fn increment(state: State<AppState>) -> i32 {
  let mut counter = state.counter.lock().unwrap();
  *counter += 1;
  *counter
}

插件集成到 Tauri 应用

1. 本地插件引用

toml 复制代码
# 主应用 Cargo.toml
[dependencies]
tauri-plugin-example = { path = "../tauri-plugin-example" }

2. 初始化插件

rust 复制代码
// main.rs
fn main() {
  tauri::Builder::default()
    .plugin(tauri_plugin_example::init())
    .run(tauri::generate_context!())
    .expect("运行失败");
}

发布插件

1. 打包发布到 crates.io

bash 复制代码
cargo publish --allow-dirty

2. 前端用户安装

bash 复制代码
npm install tauri-plugin-example

调试技巧

  1. Rust 日志输出

    rust 复制代码
    log::info!("调试信息: {:?}", data);

    启动应用时加环境变量:

    bash 复制代码
    RUST_LOG=info cargo tauri dev
  2. 前端 DevTools

    rust 复制代码
    .setup(|app| {
      #[cfg(debug_assertions)]
      app.get_window("main").unwrap().open_devtools();
      Ok(())
    })

相关插件

  1. github.com/tauri-apps/...
  2. v2.tauri.app/zh-cn/plugi...
  3. v2.tauri.app/zh-cn/devel...
相关推荐
小满zs几秒前
React-router v7 第一章(安装)
前端·react.js
程序员小续7 分钟前
前端低代码架构解析:拖拽 UI + 代码扩展是怎么实现的?
前端·javascript·面试
wangpq14 分钟前
微信小程序地图callout气泡图标在ios显示,在安卓机不显示
前端·vue.js
curdcv_po18 分钟前
Vue3 组件通信方式全解析
前端
Auroral15622 分钟前
基于RabbitMQ的异步通知系统设计与实现
前端·后端
栗筝i23 分钟前
Spring 核心技术解析【纯干货版】- XV:Spring 网络模块 Spring-Web 模块精讲
前端·网络·spring
打野赵怀真25 分钟前
H5如何禁止动画闪屏?
前端·javascript
zhangxingchao25 分钟前
关于浮点数的思考
前端
Riesenzahn26 分钟前
你喜欢Sass还是Less?为什么?
前端·javascript