Tauri是什么?

一、Tauri 是什么

Tauri 是一个用 Rust 编写应用逻辑、用 Web 技术编写界面的跨平台桌面(与移动端)应用框架。它的定位很明确:让你已经写好的前端代码直接变成原生应用,而不是重新用另一套语言重写一遍界面。

对「有 Next.js / Nuxt.js / SvelteKit 项目,但想做桌面版」这个场景来说,这正是 Tauri 最被低估的价值——你不需要重构任何前端业务逻辑。

Tauri 与 Electron 的根本差异在于渲染层:Electron 每个应用都打包一份完整的 Chromium 运行时,Tauri 则直接调用操作系统的 WebView。

平台Tauri 使用的渲染器
WindowsWebView2(Edge/Chromium 内核,系统预装或安装包内置)
macOSWKWebView(Safari 内核,系统自带)
LinuxWebKitGTK
AndroidAndroidX WebView
iOSWKWebView

这个差异带来两个直接结果:安装包体积小一个数量级,运行时内存占用也低得多。代价是渲染行为依赖系统 WebView 版本——同一份代码在老旧 Linux(WebKitGTK 较旧)上可能出现渲染差异,这是选型时需要接受的约束。

版本说明:本文基于 Tauri 2.x 编写(当前稳定线为 2.12.x,Rust crate 最低要求 Rust 1.90)。Tauri 3 已有 alpha 版本,但仍在预览阶段,生产环境请使用 2.x。如果你的项目还在 Tauri 1.x,本文第六节给出了完整迁移对照。

Tauri 2 相比 Tauri 1 变了什么

Tauri 2 不是小版本升级,几处关键变化直接影响了写法:

  • 权限模型重构:Tauri 1 的 allowlist 白名单被移除,改为 capabilities(能力)+ permissions(权限) 两层模型,权限声明在 src-tauri/capabilities/*.json 里,不再塞在 tauri.conf.json 中。
  • 配置结构重排:tauri 顶层键改名 app,bundle 提升到顶层,identifier 从 bundle 里挪到顶层。
  • 大部分原生 API 拆成插件:文件操作、对话框、通知、Shell、更新器等不再是内置 API,而是独立的插件(tauri-plugin-fs、tauri-plugin-dialog 等),按需安装。
  • 正式支持移动端:iOS 与 Android 是一等目标,不再是实验特性。

二、Tauri 的分层架构

Tauri 的架构分三层,各层职责清晰、互不越界。这也是它能兼容任意 Web 栈的根本原因。

层级组成职责
前端层(Web)HTML/CSS/JS/TS;任意 Web 框架;Tauri 前端 API 包界面渲染与业务逻辑,通过受限的 API 调用系统能力
Tauri 核心层(Rust)IPC 通信;权限与能力校验;窗口管理;托盘;自动更新;Rust 原生能力封装唯一有权触碰系统资源的一层,所有调用都要经过权限检查
原生系统层Windows:Win32 API / WebView2;macOS:AppKit / WebKit;Linux:X11/Wayland真正的系统调用

各层详解:

前端层就是你熟悉的 Web 项目(Next.js、Nuxt.js、SvelteKit 等),唯一的区别在于:开发时 Tauri 会代理你的 Web 开发服务器实现热重载,打包后加载构建产物。你无需修改任何前端业务逻辑,仅需通过 @tauri-apps/api 与插件包调用桌面端原生功能(如文件读写)。

Tauri 核心层(Rust)是应用的「大脑」,但如果你只用基础功能,无需深入掌握 Rust:

  • IPC 通信:前端与 Rust 的唯一安全通道。所有原生功能必须通过显式声明的 Command 或插件命令触发,杜绝前端随意访问系统资源。
  • 权限管理:Tauri 2 用 capabilities 精确控制「哪个窗口可以调用哪些 API」。默认沙箱隔离,你可以限制前端只能读写某个目录而无法访问系统盘。
  • 原生能力封装:窗口、托盘、文件系统等核心功能已封装好,你只需调用 API,无需自己写 Rust。

原生系统层由 Tauri 直接调用系统原生 API:Windows 上用 WebView2 渲染前端、调用 Win32 API 管理窗口;macOS 上用 WebKit 渲染前端、通过 AppKit 实现程序坞与菜单栏。

三、从零搭建一个 Tauri 2 项目

步骤 1:安装开发环境

Tauri 需要 Rust 环境加系统依赖。

# Windows(PowerShell,以管理员身份运行)
winget install Rustlang.Rustup
rustup default stable

1. macOS(终端)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env

系统依赖:

系统依赖项安装命令
WindowsWebView2 + C++ 构建工具安装 Visual Studio 2022(勾选「桌面开发 C++」);WebView2 运行时通常已预装
macOSXcode 命令行工具xcode-select --install
Linuxwebkit2gtk、build-essential 等依发行版安装 libwebkit2gtk-4.1-dev 等

步骤 2:创建项目

方式一:给已有 Web 项目接入(推荐)

cd my-next-app
npm install -D @tauri-apps/cli@latest
npx tauri init

交互提问按你的项目回答。关键是这几项:

  • 应用名与窗口标题
  • 前端资源目录:Next.js 填 ../out,Nuxt.js 填 ../.output/public,SvelteKit 填 ../build
  • 开发服务器地址:http://localhost:3000(Next.js)、http://localhost:5173(SvelteKit)
  • 前端开发命令:npm run dev
  • 前端构建命令:npm run build

方式二:从零创建

npm create tauri-app@latest

步骤 3:核心配置(tauri.conf.json)

Tauri 2 的配置结构与 1.x 差别很大。下面是一个可直接使用的最小配置:

{
  "identifier": "com.yourname.myapp",
  "productName": "MyApp",
  "version": "0.1.0",
  "app": {
    "windows": [
      {
        "label": "main",
        "title": "My App",
        "width": 1200,
        "height": 800,
        "resizable": true
      }
    ],
    "security": {
      "csp": null
    }
  },
  "build": {
    "beforeDevCommand": "npm run dev",
    "beforeBuildCommand": "npm run build",
    "devUrl": "http://localhost:3000",
    "frontendDist": "../out"
  },
  "bundle": {
    "active": true,
    "targets": "all",
    "icon": [
      "icons/32x32.png",
      "icons/128x128.png",
      "icons/128x128@2x.png",
      "icons/icon.icns",
      "icons/icon.ico"
    ]
  }
}

几个必须记住的字段位置:

  • identifier 在顶层,不在 bundle 里。这是应用的唯一标识(Bundle ID、WebView 数据目录都用它),必须改成你自己的反向域名,com.tauri.dev 默认值不能用于正式构建。
  • productName 与 version 也在顶层(1.x 藏在 package 对象里)。
  • app 取代了 1.x 的 tauri 键,窗口、托盘、安全策略都放这里。
  • build.frontendDist 对应 1.x 的 distDir;build.devUrl 对应 1.x 的 devPath。
  • bundle 提升到顶层,平台相关配置下沉为 bundle.windows、bundle.macOS、bundle.linux。

步骤 4:声明权限(capabilities)

这是 Tauri 2 与 1.x 差别最大、也最容易漏掉的一步。默认情况下前端能调用的系统 API 极少,你需要显式授权。

创建 src-tauri/capabilities/default.json:

{
  "$schema": "../gen/schemas/desktop-schema.json",
  "identifier": "main-capability",
  "description": "主窗口的基础能力",
  "windows": ["main"],
  "permissions": [
    "core:default",
    "core:window:allow-set-title",
    "fs:allow-read-text-file",
    "fs:allow-write-text-file",
    "dialog:allow-open",
    "dialog:allow-save"
  ]
}

权限命名的规律是 <插件>:<动作>,核心 API 则是 core:<模块>:<动作>。写权限时遵循最小授权原则——只给真正需要的动作。core:default 是聚合权限,会一次性放开 app、event、image、menu、path、resources、tray、webview、window 九个核心模块的默认权限集;如果你对窗口或托盘没有需求,可以只列具体模块的 core:<模块>:default,甚至逐条列出 core:window:allow-xxx。

需要注意的是,<插件>:default 这类聚合权限通常会给出一整套能力(如 fs:default 覆盖全部文件操作),配置时应当用它替换掉宽泛的默认项,而不是与细粒度权限叠加。

src-tauri/capabilities/ 目录下的所有能力文件默认全部启用;一旦你在 tauri.conf.json 的 app.security.capabilities 里显式列出了能力标识,就只有被列出的那些生效。

关于 fs 插件的 scope:文件类权限分两层,命令授权与路径范围必须同时满足,只有一层是无效的。

{
  "$schema": "../gen/schemas/desktop-schema.json",
  "identifier": "fs-capability",
  "description": "应用数据目录读写",
  "windows": ["main"],
  "permissions": [
    "fs:allow-read-text-file",
    "fs:allow-write-text-file",
    {
      "identifier": "fs:allow-read-text-file",
      "allow": [{ "path": "$APPDATA/*" }]
    },
    {
      "identifier": "fs:allow-write-text-file",
      "allow": [{ "path": "$APPDATA/*" }]
    }
  ]
}

路径占位符 $APPDATA、$APPCONFIG、$APPLOCALDATA 指向应用自己的数据目录,$HOME、$DOCUMENT、$DESKTOP 等指向系统用户目录。* 匹配一层,** 匹配多层;deny 规则优先于 allow。

步骤 5:安装插件

用到的原生能力需要单独安装插件。Rust 侧加依赖,JS 侧加对应的 npm 包:

# Rust 侧(src-tauri/Cargo.toml)
cargo add tauri-plugin-fs tauri-plugin-dialog tauri-plugin-opener

1. JS 侧
npm install @tauri-apps/plugin-fs @tauri-apps/plugin-dialog @tauri-apps/plugin-opener

插件在 src-tauri/src/lib.rs 中注册:

fn run() {
    tauri::Builder::default()
        .plugin(tauri_plugin_fs::init())
        .plugin(tauri_plugin_dialog::init())
        .plugin(tauri_plugin_opener::init())
        .invoke_handler(tauri::generate_handler![get_system_info])
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

步骤 6:开发与调试

npm run tauri dev

Tauri 会先启动你的 Web 开发服务器,再拉起应用窗口。修改前端代码后窗口自动热更新,体验与 Web 开发基本一致。

步骤 7:调用原生功能

文件系统(插件方式)

import { useState } from 'react';
import { readTextFile, writeTextFile, BaseDirectory } from '@tauri-apps/plugin-fs';

export default function Home() {
  const [content, setContent] = useState('');

  const writeFile = async () => {
    await writeTextFile('test.txt', 'Hello Tauri!', { baseDir: BaseDirectory.Document });
  };

  const readFile = async () => {
    setContent(await readTextFile('test.txt', { baseDir: BaseDirectory.Document }));
  };

  return (
    <div style={{ padding: 20 }}>
      <button onClick={writeFile}>写入文件</button>
      <button onClick={readFile}>读取文件</button>
      <div>文件内容:{content}</div>
    </div>
  );
}

注意选项名是 baseDir(不是 dir)。BaseDirectory.Document 只是「用户文档目录」的语义化别名,真正决定前端能访问哪些路径的是 capabilities 里的权限与 scope 配置——命令授权与路径 scope 两者缺一不可:只声明 fs:allow-read-text-file 而没有对应 scope,调用依然会被拒绝。

自定义 Rust Command(进阶)

需要调用系统 API 或做复杂逻辑时,才需要写 Rust:

// src-tauri/src/lib.rs
#[tauri::command]
fn get_system_info() -> String {
    let os = std::env::consts::OS;
    format!("当前系统:{}", os)
}

前端调用:

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

const getSysInfo = async () => {
  const res = await invoke<string>('get_system_info');
  alert(res);
};

步骤 8:打包

npm run tauri build

产物在 src-tauri/target/release/bundle/:

  • Windows:msi/(安装包)与 nsis/(安装程序),路径 src-tauri/target/release/bundle/msi/
  • macOS:dmg/(磁盘镜像)与 macos/(.app 包),路径 src-tauri/target/release/bundle/dmg/

四、Tauri 2 常用插件清单

Tauri 2 的系统能力基本都拆成了插件,按需安装。下面是桌面端最常用的一批:

能力Rust cratenpm 包说明
文件系统tauri-plugin-fs@tauri-apps/plugin-fs读写文件与目录,受 scope 限制
对话框tauri-plugin-dialog@tauri-apps/plugin-dialog打开/保存文件、消息框
打开外部链接tauri-plugin-opener@tauri-apps/plugin-opener用系统默认程序打开 URL 或文件
通知tauri-plugin-notification@tauri-apps/plugin-notification系统通知
剪贴板tauri-plugin-clipboard-manager@tauri-apps/plugin-clipboard-manager读写剪贴板
自动更新tauri-plugin-updater@tauri-apps/plugin-updater应用内更新
Shelltauri-plugin-shell@tauri-apps/plugin-shell执行外部命令(需谨慎授权)
全局快捷键tauri-plugin-global-shortcut@tauri-apps/plugin-global-shortcut注册系统级快捷键
窗口状态tauri-plugin-window-state@tauri-apps/plugin-window-state记忆窗口大小与位置
单实例tauri-plugin-single-instance@tauri-apps/plugin-single-instance保证应用只启动一次
存储tauri-plugin-store@tauri-apps/plugin-store键值持久化
深度链接tauri-plugin-deep-link@tauri-apps/plugin-deep-link自定义协议唤起应用

核心 API(窗口、事件、菜单、托盘等)仍在 @tauri-apps/api 里,不需要额外装插件:

import { getCurrentWindow } from '@tauri-apps/api/window';

const win = getCurrentWindow();
await win.setTitle('新标题');
await win.minimize();

五、Tauri 与 Electron 的对比

维度Tauri 2Electron
包体积几 MB 量级(不打包 Chromium)数十至上百 MB
内存占用低,无独立 Chromium 进程高,Chromium 多进程模型
渲染一致性依赖系统 WebView 版本,不同系统有差异打包固定版本 Chromium,各系统一致
前后端语言Rust(后端)+ Web(前端)Node.js(后端)+ Web(前端)
安全模型capabilities 细粒度授权,默认最小权限Node.js 权限较宽,需自行约束
开发环境需要装 Rust需要装 Node.js
生态成熟度插件生态持续发展中,官方 30+ 插件生态极其成熟,npm 上大量现成方案
移动端官方支持 iOS / Android官方不支持
最低系统要求受系统 WebView 版本影响由打包的 Chromium 版本决定

怎么选:如果你的用户群体是技术用户、工具类应用、对安装包体积敏感、且愿意接受跨系统渲染差异,Tauri 更合适。如果你的应用高度依赖特定 Chromium 行为、需要大量 npm 现成方案(如音视频编辑、复杂表格渲染),或者团队只有前端背景不想碰 Rust,Electron 的风险更低。

这不是「谁更先进」的问题,而是约束条件不同。

六、从 Tauri 1 迁移到 Tauri 2

如果你已有 Tauri 1.x 项目,官方提供了 tauri migrate 命令自动完成大部分机械替换:

npm install @tauri-apps/cli@latest
npm run tauri migrate

它会重写 tauri.conf.json、把 v1 的 allowlist 转成默认的 capability 文件、升级 Cargo 依赖、添加对应的插件 crate。但它不修改你的 Rust 源码和 JS import——那部分需要手工处理。

关键字段对照:

Tauri 1Tauri 2
package.productName / package.version顶层 productName / version
package 整个对象已移除
tauriapp
tauri.allowlist已移除,改为 src-tauri/capabilities/*.json
tauri.allowlist.protocol.assetScopeapp.security.assetProtocol.scope
tauri.bundle顶层 bundle
tauri.bundle.identifier顶层 identifier
tauri.bundle.dmg / deb / appimagebundle.macOS.dmg / bundle.linux.deb / bundle.linux.appimage
tauri.cliplugins.cli
tauri.systemTrayapp.trayIcon
tauri.patternapp.security.pattern
tauri.updaterplugins.updater,并需设 bundle.createUpdaterArtifacts
tauri.windows[].fileDropEnabledapp.windows[].dragDropEnabled
build.distDirbuild.frontendDist
build.devPathbuild.devUrl
build.withGlobalTauriapp.withGlobalTauri

Rust crate 侧的拆分明细:

Tauri 1Tauri 2
api::dialogtauri-plugin-dialog
api::httptauri-plugin-http
api::process / api::shelltauri-plugin-shell
api::fstauri-plugin-fs,或直接用 Rust 标准库 std::fs
api::versionsemver crate
api::pathtauri::Manager::path
App::clipboard_managertauri-plugin-clipboard-manager
App::global_shortcut_managertauri-plugin-global-shortcut

JS 侧的 import 路径同样要改:@tauri-apps/api/fs → @tauri-apps/plugin-fs,@tauri-apps/api/http → @tauri-apps/plugin-http,@tauri-apps/api/shell → @tauri-apps/plugin-shell。

另外 Rust 的 Window 类型在 2.x 中改名为 WebviewWindow(为多 WebView 让位),如果你在 Rust 侧直接操作窗口,需要同步调整。

七、适配常见 Web 框架

接入 Tauri 的核心是「配置静态导出 + 指定产物目录」:

Web 框架静态导出配置frontendDist开发服务器
Next.jsnext.config.js 中设 output: 'export'../outhttp://localhost:3000
Nuxt.jsnuxt.config.ts 中设 ssr: false + nitro: { preset: 'static' }../.output/publichttp://localhost:3000
SvelteKitsvelte.config.js 中设 kit: { adapter: adapter-static() }../buildhttp://localhost:5173

需要注意的几点:

  • SSR 必须关闭。Tauri 打包的是静态文件,无法运行服务端代码。Next.js / Nuxt.js 若开启了 SSR,需先改为静态导出。
  • 路由建议用哈希路由(如 /#/about),避免刷新时静态资源路径解析出错。Next.js 可设 assetPrefix: './',SvelteKit 可设 kit: { router: { mode: 'hash' } }。
  • Next.js 需要注意:Next.js 静态导出不支持服务端 API Route、ISR、动态路由的 getStaticPaths 需改为静态参数;如果你的项目重度依赖这些能力,Tauri 的适配成本会显著上升。

八、常见问题排查

  1. Windows 提示缺少 WebView2:多数 Windows 10/11 已预装。若目标用户是 Windows 7 或精简版系统,需要在 bundle.windows.webviewInstallMode 中配置为离线安装模式,把运行时打进安装包。
  2. macOS 打包签名报错:正式分发需要配置代码签名与公证(notarization)。仅本地测试可用 npm run tauri build -- --no-bundle 跳过打包环节。
  3. 前端调用插件 API 报权限错误:这是 Tauri 2 最常见的困惑来源。检查 src-tauri/capabilities/*.json 里是否声明了对应权限,以及 windows 字段是否覆盖了你的窗口 label。
  4. 文件读写被拒绝:权限声明正确但路径不在允许范围内时,需要额外配置 scope。fs 插件的 scope 定义允许访问的目录。
  5. 前端路由 404:静态导出后确认路由模式与资源前缀配置,必要时改用哈希路由。
  6. Linux 上渲染异常:多为系统 WebKitGTK 版本过旧。Tauri 2.x 起要求 libwebkit2gtk-4.1(4.0 属 1.x 时代);发行版版本过低时需要自行编译或使用 Flatpak 分发。

九、总结

  1. Tauri 2 的核心价值是让现有 Web 项目直接变成原生应用,且安装包体积与内存占用都远优于 Electron。代价是渲染行为依赖系统 WebView,且需要引入 Rust 工具链。
  2. 与 Tauri 1 相比,最大的变化是权限模型从 allowlist 改为 capabilities + permissions 插件化架构。迁移时用官方 tauri migrate 处理机械部分,Rust 源码与 JS import 需手工调整。
  3. 落地顺序建议:先用 tauri init 接入已有 Web 项目跑通 tauri dev,再按需加插件与 capabilities,最后才考虑自定义 Rust Command。这样能把「Rust 学习成本」推迟到你真正需要写 Rust 的时候。

官方资料:Tauri 2 官方文档;GitHub tauri-apps/tauri。

暂无评论

发送评论 编辑评论

|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇