应用端实验室桌面应用
00 / 00

Runtime 与权限

理解 Runtime Adapter、Tauri commands、capabilities、系统权限和浏览器 fallback

你将学到

  • Runtime Adapter 的作用和它为什么把原生调用隔离在独立文件里
  • 模板当前有哪些 adapter 文件和 Rust commands
  • Tauri v2 的 capability 模型如何控制前端能调什么
  • 操作系统层面还有哪些权限是 Tauri 管不了的
  • 新增一个本地能力需要改哪些地方、按什么顺序改

为什么要有 Runtime Adapter

Tauri 应用由两部分组成:前端 WebView 负责界面,Rust runtime 负责系统能力。两边通过 Tauri command 或 plugin 通信。

如果不加约束,前端组件会到处散落 invoke() 调用和 plugin import。改一个原生能力要翻遍整个前端代码,浏览器预览也跑不起来。

模板把所有 Tauri 相关调用集中放在 products/01mvp/apps/desktop/src/runtime 目录。React 组件只调 adapter 导出的函数,不直接碰 Tauri API。这样做有三个好处:

  • React 组件不需要到处写 invoke 和 plugin import,只调 adapter 就行
  • 浏览器预览模式下 adapter 会返回 fallback,UI 依然能跑
  • 新增系统能力时有统一的测试和排查入口

当前 adapter 文件

模板里每个 adapter 文件负责一个领域:

文件负责什么
core.ts判断是否运行在 Tauri、封装 invoke 和可选 plugin import
preferences.ts读取、保存、重置桌面偏好
app-info.ts读取应用名、版本和 identifier
opener.ts打开外部 URL 或 app data 目录
updater.ts预留自动更新检查入口

浏览器预览没有真实 Tauri runtime。模板会返回 unavailable 状态,或用 localStorage 保存临时偏好。这个 fallback 让你不用每次都启动原生窗口就能开发和调试 UI。

新增原生能力时,在 src/runtime 下建一个新文件。不要把 Tauri 调用写进组件或路由 loader 里。

Rust Commands

前端调原生能力的桥梁是 Rust command。当前命令定义在:

products/01mvp/apps/desktop/src-tauri/src/lib.rs

模板提供四个命令:

命令作用
get_desktop_preferences从 app data 读取桌面偏好 JSON
set_desktop_preferences把偏好写入 app data
reset_desktop_preferences删除偏好文件,恢复默认值
open_app_data_dir用系统文件管理器打开 app data 目录

前端通过 core.ts 里的 invokeTauri() 调用这些命令。不要在组件里直接写 invoke("get_desktop_preferences"),统一走 adapter 层。

新增命令后,要把它注册到 invoke handler 里:

.invoke_handler(tauri::generate_handler![
    get_desktop_preferences,
    open_app_data_dir,
    reset_desktop_preferences,
    set_desktop_preferences
])

漏注册是最常见的新手错误:Rust 侧写好了命令,前端调用时却报 "command not found"。

Capabilities

Tauri v2 用 capabilities 控制前端能调用哪些命令和 plugin。这是安全模型的核心:即使 Rust 侧注册了命令,没有在 capability 里开放权限,前端也调不通。

模板的配置在:

products/01mvp/apps/desktop/src-tauri/capabilities/default.json

当前只开放三个基础权限:

{
  "permissions": ["core:default", "opener:default", "process:default"]
}

core:default 允许基础窗口和事件操作。opener:default 允许打开外部链接。process:default 允许退出应用。

新增 plugin 时只开放产品真正需要的权限。比如你只需要检查更新,就优先用 updater 的 check 权限,不要直接开放完整安装流程。

官方文档:Tauri permissions

系统权限

有些能力不是 Tauri capabilities 能完全决定的。操作系统还会单独要求用户授权。即使 Tauri 侧放行了,用户拒绝系统弹窗后功能一样用不了。

能力macOSWindowsLinux
麦克风Microphone 权限隐私设置PipeWire / PulseAudio
截屏Screen Recording 权限屏幕捕获权限通常不需要
全局快捷键Accessibility全局快捷键支持X11/Wayland 差异
输入监听Input Monitoring全局钩子权限取决于桌面环境
文件读取文件选择器或 FDE文件选择器文件选择器

模板默认不启用这些能力。你的产品需要用到时,要做三件事:在 UI 里解释为什么需要这个权限、检测当前权限状态、引导用户去系统设置里授权。

如何新增本地能力

如果产品需要一个 Tauri 没有现成 plugin 的功能,按这个顺序走:

确认需要原生 runtime

先写清楚这个能力为什么浏览器做不了。如果只是 HTTP 请求、DOM 操作或 IndexedDB,不需要原生能力。

选择 plugin 或 command

找官方 plugin 或成熟第三方 plugin,避免手写平台底层逻辑。Tauri 官方 plugin 列表覆盖了常见的文件系统、通知、剪贴板、全局快捷键等场景。

Rust 侧注册

lib.rs 里注册 plugin 或定义 command。如果是自定义 command,记得加 #[tauri::command] 标注。

开放 capability 权限

capabilities/default.json 里添加必要的权限。只开放你用到的权限,不要图省事全开。

封装 adapter

src/runtime/<feature>.ts 里封装调用逻辑,并提供浏览器 fallback。fallback 可以返回 unavailable 状态,或者用 localStorage 模拟。

UI 展示不可用状态

在组件里处理 adapter 返回的 unavailable 状态。展示可理解的提示,而不是空白或报错。

原生窗口验收

vpr @01mvp/desktop#tauri:dev 在真实桌面窗口里验证。浏览器预览不能替代这一步。

浏览器预览能证明布局、普通 React 状态和 HTTP API。它不能证明 Tauri command 能调用、app data 能写入、tray 能出现、系统权限能弹窗、签名后的 app 能被识别。涉及原生能力的改动,必须跑 vpr @01mvp/desktop#tauri:dev 验收。

Plugin 怎么加

新增一个 Tauri plugin 通常要改三处:

  1. products/01mvp/apps/desktop/package.json -- 添加 JS 绑定(npm 包)
  2. products/01mvp/apps/desktop/src-tauri/Cargo.toml -- 添加 Rust crate
  3. src-tauri/src/lib.rs -- 调用 .plugin() 注册,并在 capabilities 里开放权限

前端使用时,不要在组件里直接 import plugin。先在 src/runtime/<feature>.ts 封装一层 adapter,保持架构统一。这样做的另一个好处是:如果以后要换 plugin 实现,只需要改 adapter 文件,不用动 UI 代码。

浏览器预览 vs Tauri 原生窗口

两种模式能验证的东西不一样。选错验证模式是桌面端最常见的遗漏。

验收项浏览器预览Tauri 原生窗口
布局和样式
React 状态和路由
HTTP API 调用
登录和 auth 流程
Tauri command不能
app data 读写不能
系统托盘不能
系统权限弹窗不能
窗口关闭/隐藏行为不能
签名和公证验证不能

日常开发用浏览器预览看 UI 就够了,启动快、热更新也方便。改到原生能力相关代码时,必须切到 Tauri 原生窗口验证。验证命令:

vpr @01mvp/desktop#tauri:dev

跑完 Rust 检查确认编译没问题:

vpr @01mvp/desktop#tauri:check

下一步

了解了 Runtime 和权限体系后,下一步去看 本地存储,了解桌面应用里该把数据放在哪里。

想和其他创造者交流?

这篇文档有问题?