从 Tauri 1.0 升级
本指南将会引导你将 Tauri 1.0 应用程序升级到 Tauri 2.0 版本。
Tauri 的移动端界面要求你的项目输出链接库(shared library)。如果你的现有应用程序以支持移动端为目标,则必须更改你的 crate 类型,以便在生成桌面端可执行文件的同时也生成链接库。
- 添加下列配置到你的 Cargo 配置文件以生成链接库。
[lib]name = "app_lib"crate-type = ["staticlib", "cdylib", "rlib"]-
将
src-tauri/src/main.rs重命名为src-tauri/src/lib.rs。这一文件同时被桌面端和移动端的构建结果共享。 -
将
lib.rs中的main函数头修改为:
#[cfg_attr(mobile, tauri::mobile_entry_point)]pub fn run() { // 在这里编写你的代码}tauri::mobile_entry_point 宏会在编译为移动端库时处理你的入口函数。
- 重新创建
main.rs并调用刚刚创建的共享的run函数:
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
fn main() { app_lib::run();}Tauri v2 的命令行工具包括一个 migrate 命令,可自动执行大部分流程,并帮助你完成迁移:
npm install @tauri-apps/cli@latestnpm run tauri migrateyarn upgrade @tauri-apps/cli@latestyarn tauri migratepnpm update @tauri-apps/cli@latestpnpm tauri migratecargo install tauri-cli --version "^2.0.0" --lockedcargo tauri migrate在命令行界面参考中了解有关 migrate 命令的更多信息。
以下是 Tauri 1.0 到 Tauri 2.0 的变化摘要:
- 移动
package > productName和package > version至顶层字段。 - 生成的二进制文件不会根据
productName自动重新命名,所以你需要在配置的顶层增加mainBinaryName来匹配productName。 - 移除
package。 - 重命名
tauri键为app。 - 移除
tauri > allowlist。详情参考迁移授权许可。 - 移动
tauri > allowlist > protocol > assetScope至app > security > assetProtocol > scope。 - 移动
tauri > cli至plugins > cli。 - 重命名
tauri > windows > fileDropEnabled为app > windows > dragDropEnabled。 - 移除
tauri > updater > active。 - 移除
tauri > updater > dialog。 - 移动
tauri > updater至plugins > updater。 - 增加
bundle > createUpdaterArtifacts。如果此应用程序使用了更新程序(app updater),则必须设定此值。- 当从使用 v1 版本已分发的程序升级时,需设定此值为
v1Compatible。详情请参考升级向导。
- 当从使用 v1 版本已分发的程序升级时,需设定此值为
- 重命名
tauri > systemTray为app > trayIcon。 - 移动
tauri > pattern至app > security > pattern。 - 移动
tauri > bundle到顶层。 - 移动
tauri > bundle > dmg至bundle > macOS > dmg。 - 移动
tauri > bundle > deb至bundle > linux > deb。 - 移动
tauri > bundle > appimage至bundle > linux > appimage。 - 移除
tauri > bundle > macOS > license,使用bundle > licenseFile作为替代。 - 移除
tauri > bundle > windows > wix > license,使用bundle > licenseFile作为替代。 - 移除
tauri > bundle > windows > nsis > license, 使用bundle > licenseFile作为替代。 - 移动
build > withGlobalTauri至app > withGlobalTauri。 - 重命名
build > distDir为frontendDist。 - 重命名
build > devPath为devUrl。
- linux-protocol-body:启用自定义协议请求体解析,并允许 IPC 使用它。需要 webkit2gtk 2.40。
- reqwest-client:reqwest 现在是唯一受支持的客户端。
- reqwest-native-tls-vendored:使用
native-tls-vendored作为替代。 - process-command-api:使用
shell插件作为替代(见下节说明)。 - shell-open-api:使用
shell插件作为替代(见下节说明)。 - windows7-compat:被移动到
notification插件。 - updater:updater 现在是一个插件。
- linux-protocol-headers:现在默认启动,因为我们更新了最低 webkit2gtk 版本支持。
- system-tray:重命名为
tray-icon。
api模块被移除。每个 API 模块都可以在 Tauri 插件中找到。api::dialog模块被移除。使用tauri-plugin-dialog作为替代。查看详情api::file模块被移除。使用 Rust 的std::fs作为替代。api::http模块被移除。使用tauri-plugin-http作为替代。查看详情api::ip模块被重写并被移动到tauri::ipc。查看新的应用程序接口,特别是tauri::ipc::Channel。api::path模块中的函数和tauri::PathResolved被移动到tauri::Manager::path。查看详情api::process::Command、tauri::api::shell和tauri::Manager::shell_scopeAPI 被移除。使用tauri-plugin-shell作为替代。查看详情api::process::current_binary和tauri::api::process::restart被移动到tauri::process。api::versionmodule has been 被移除。使用 semver crate 作为替代。App::clipboard_manager和AppHandle::clipboard_manager被移除。使用tauri-plugin-clipboard作为替代。查看详情App::get_cli_matches被移除。使用tauri-plugin-cli作为替代。查看详情App::global_shortcut_manager和AppHandle::global_shortcut_manager被移除。使用tauri-plugin-global-shortcut作为替代。查看详情Manager::fs_scope被移除。文件系统范围可通过tauri_plugin_fs::FsExt访问。Plugin::PluginApi现在会接收一个插件的配置作为第二个参数。Plugin::setup_with_config被移除。使用更新后的tauri::Plugin::PluginApi作为替代。scope::ipc::RemoteDomainAccessScope::enable_tauri_api和scope::ipc::RemoteDomainAccessScope::enables_tauri_api被移除。通过scope::ipc::RemoteDomainAccessScope::add_plugin单独启用每个核心插件。scope::IpcScope被移除。使用scope::ipc::Scope作为替代。scope::FsScope、scope::GlobPattern和scope::FsScopeEvent被移除。分别使用scope::fs::Scope、scope::fs::Pattern和scope::fs::Event作为替代。updater模块被移除。使用tauri-plugin-updater作为替代。查看详情Env.args字段被移除。使用Env.args_os字段作为替代。Menu、MenuEvent、CustomMenuItem、Submenu、WindowMenuEvent、MenuItem和Builder::on_menu_eventAPI 被移除。查看详情SystemTray、SystemTrayHandle、SystemTrayMenu、SystemTrayMenuItemHandle、SystemTraySubmenu、MenuEntry和SystemTrayMenuItemAPI 被移除。查看详情
@tauri-apps/api 包不再提供非核心模块。只有先前的 tauri(现在的 core)、path、event 和 window 模块被导出。
其他的模块被分离移至插件中。
@tauri-apps/api/tauri模块被重命名为@tauri-apps/api/core。查看详情@tauri-apps/api/cli模块被移除。使用@tauri-apps/plugin-cli作为替代。查看详情@tauri-apps/api/clipboard模块被移除。使用@tauri-apps/plugin-clipboard作为替代。查看详情@tauri-apps/api/dialog模块被移除。使用@tauri-apps/plugin-dialog作为替代。查看详情@tauri-apps/api/fs模块被移除。使用@tauri-apps/plugin-fs作为替代。查看详情@tauri-apps/api/global-shortcut模块被移除。使用@tauri-apps/plugin-global-shortcut作为替代。查看详情@tauri-apps/api/http模块被移除。使用@tauri-apps/plugin-http作为替代。查看详情@tauri-apps/api/os模块被移除。使用@tauri-apps/plugin-os作为替代。查看详情@tauri-apps/api/notification模块被移除。使用@tauri-apps/plugin-notification作为替代。查看详情@tauri-apps/api/process模块被移除。使用@tauri-apps/plugin-process作为替代。查看详情@tauri-apps/api/shell模块被移除。使用@tauri-apps/plugin-shell作为替代。查看详情@tauri-apps/api/updater模块被移除。使用@tauri-apps/plugin-updater作为替代。查看详情@tauri-apps/api/window模块被重命名为@tauri-apps/api/webviewWindow。查看详情
Tauri 命令行工具读取和写入的大部分环境变量都重新命名,以保持一致性并防止出错:
TAURI_PRIVATE_KEY->TAURI_SIGNING_PRIVATE_KEYTAURI_KEY_PASSWORD->TAURI_SIGNING_PRIVATE_KEY_PASSWORDTAURI_SKIP_DEVSERVER_CHECK->TAURI_CLI_NO_DEV_SERVER_WAITTAURI_DEV_SERVER_PORT->TAURI_CLI_PORTTAURI_PATH_DEPTH->TAURI_CLI_CONFIG_DEPTHTAURI_FIPS_COMPLIANT->TAURI_BUNDLER_WIX_FIPS_COMPLIANTTAURI_DEV_WATCHER_IGNORE_FILE->TAURI_CLI_WATCHER_IGNORE_FILENAMETAURI_TRAY->TAURI_LINUX_AYATANA_APPINDICATORTAURI_APPLE_DEVELOPMENT_TEAM->APPLE_DEVELOPMENT_TEAMTAURI_PLATFORM->TAURI_ENV_PLATFORMTAURI_ARCH->TAURI_ENV_ARCHTAURI_FAMILY->TAURI_ENV_FAMILYTAURI_PLATFORM_VERSION->TAURI_ENV_PLATFORM_VERSIONTAURI_PLATFORM_TYPE->TAURI_ENV_PLATFORM_TYPETAURI_DEBUG->TAURI_ENV_DEBUG
事件系统经过重新设计,更易于使用。现在,它不再依赖于事件源,而是依赖于事件目标,实现起来更加简单。
emit函数现在会向所有事件侦听器发送事件。- 添加一个新的
emit_to函数以向特定目标触发事件。 emit_filter现在基于EventTarget进行过滤,而不是基于一个视窗。- 将
listen_global重命名为listen_any。现在,它可以监听所有事件,无论其过滤器和目标是什么。
Tauri v2 引入了多 webview 支持,目前处在 unstable feature 标识之后。
为了支持这一功能,我们将 Rust 的 Window 类型重命名为 WebviewWindow、Manager 的 get_window 函数重命名为 get_webview_window。
WebviewWindow JS API 类型现在是从 @tauri-apps/api/webviewWindow 中重导出,而不是从 @tauri-apps/api/window 中。
将 Tauri 1.0 应用程序迁移到 Tauri 2.0 时可能遇到的常见情况。
@tauri-apps/api/tauri 模块被重命名为 @tauri-apps/api/core。
只需要修改你的导入路径:
import { invoke } from "@tauri-apps/api/tauri"import { invoke } from "@tauri-apps/api/core"Rust 的 App::get_cli_matches 和 JavaScript 的 @tauri-apps/api/cli API 被移除。使用 @tauri-apps/plugin-cli 插件作为替代:
- 添加 Cargo 依赖项:
[dependencies]tauri-plugin-cli = "2"- 在 JavaScript 或 Rust 项目中使用:
fn main() { tauri::Builder::default() .plugin(tauri_plugin_cli::init())}{ "dependencies": { "@tauri-apps/plugin-cli": "^2.0.0" }}import { getMatches } from '@tauri-apps/plugin-cli';const matches = await getMatches();fn main() { use tauri_plugin_cli::CliExt; tauri::Builder::default() .plugin(tauri_plugin_cli::init()) .setup(|app| { let cli_matches = app.cli().matches()?; Ok(()) })}Rust 的 App::clipboard_manager 和 AppHandle::clipboard_manager 以及 JavaScript 的 @tauri-apps/api/clipboard API 被移除。使用 @tauri-apps/plugin-clipboard-manager 插件作为替代:
[dependencies]tauri-plugin-clipboard-manager = "2"fn main() { tauri::Builder::default() .plugin(tauri_plugin_clipboard_manager::init())}{ "dependencies": { "@tauri-apps/plugin-clipboard-manager": "^2.0.0" }}import { writeText, readText } from '@tauri-apps/plugin-clipboard-manager';await writeText('Tauri is awesome!');assert(await readText(), 'Tauri is awesome!');use tauri_plugin_clipboard::{ClipboardExt, ClipKind};tauri::Builder::default() .plugin(tauri_plugin_clipboard::init()) .setup(|app| { app.clipboard().write(ClipKind::PlainText { label: None, text: "Tauri is awesome!".into(), })?; Ok(()) })Rust 的 tauri::api::dialog 和 JavaScript 的 @tauri-apps/api/dialog API 被移除。使用 @tauri-apps/plugin-dialog 插件作为替代:
- 添加 Cargo 依赖项:
[dependencies]tauri-plugin-dialog = "2"- 在 JavaScript 或 Rust 项目中使用:
fn main() { tauri::Builder::default() .plugin(tauri_plugin_dialog::init())}{ "dependencies": { "@tauri-apps/plugin-dialog": "^2.0.0" }}import { save } from '@tauri-apps/plugin-dialog';const filePath = await save({ filters: [ { name: 'Image', extensions: ['png', 'jpeg'], }, ],});use tauri_plugin_dialog::DialogExt;tauri::Builder::default() .plugin(tauri_plugin_dialog::init()) .setup(|app| { app.dialog().file().pick_file(|file_path| { // 对此处的可选文件路径进行处理 // 如果用户关闭了对话框,则文件路径为 `None`。 });
app.dialog().message("Tauri is Awesome!").show(); Ok(()) })Rust 的 App::get_cli_matches 和 JavaScript 的 @tauri-apps/api/fs API 被移除。使用 Rust 的 std::fs 或 JavaScript 的 @tauri-apps/plugin-fs 插件作为替代:
- 添加 Cargo 依赖项:
[dependencies]tauri-plugin-fs = "2"- 在 JavaScript 或 Rust 项目中使用:
fn main() { tauri::Builder::default() .plugin(tauri_plugin_fs::init())}{ "dependencies": { "@tauri-apps/plugin-fs": "^2.0.0" }}import { mkdir, BaseDirectory } from '@tauri-apps/plugin-fs';await mkdir('db', { baseDir: BaseDirectory.AppLocalData });一些函数和类型被重命名或移除:
Dir枚举别名(enum alias)被移除。使用BaseDirectory。FileEntry、FsBinaryFileOption、FsDirOptions、FsOptions、FsTextFileOption和BinaryFileContents接口和类型别名被移除,并被与每个对应的函数相匹配的接口取代。createDir被重命名为mkdir。readBinaryFile被重命名为readFile。removeDir被移除并被remove取代。removeFile被移除并被remove取代。renameFile被移除并被rename取代。writeBinaryFile被重命名为writeFile。
使用 Rust std::fs 中的函数。
Rust 的 App::global_shortcut_manager 和 AppHandle::global_shortcut_manager 以及 JavaScript 的 @tauri-apps/api/global-shortcut API 被移除。使用 @tauri-apps/plugin-global-shortcut 插件作为替代:
- 添加 Cargo 依赖项:
[dependencies][target."cfg(not(any(target_os = \"android\", target_os = \"ios\")))".dependencies]tauri-plugin-global-shortcut = "2"- 在 JavaScript 或 Rust 项目中使用:
fn main() { tauri::Builder::default() .plugin(tauri_plugin_global_shortcut::Builder::default().build())}{ "dependencies": { "@tauri-apps/plugin-global-shortcut": "^2.0.0" }}import { register } from '@tauri-apps/plugin-global-shortcut';await register('CommandOrControl+Shift+C', () => { console.log('Shortcut triggered');});use tauri_plugin_global_shortcut::GlobalShortcutExt;
tauri::Builder::default() .plugin( tauri_plugin_global_shortcut::Builder::new().with_handler(|app, shortcut| { println!("Shortcut triggered: {:?}", shortcut); }) .build(), ) .setup(|app| { // 注册全局快捷方式 // 在 macOS 上使用 Cmd 键 // 在 Windows 和 Linux 系统中,使用 Ctrl 键 app.global_shortcut().register("CmdOrCtrl+Y")?; Ok(()) })Rust 的 tauri::api::http 和 JavaScript 的 @tauri-apps/api/http API 被移除。使用 @tauri-apps/plugin-http 插件作为替代:
- 添加 Cargo 依赖项:
[dependencies]tauri-plugin-http = "2"- 在 JavaScript 或 Rust 项目中使用:
fn main() { tauri::Builder::default() .plugin(tauri_plugin_http::init())}{ "dependencies": { "@tauri-apps/plugin-http": "^2.0.0" }}import { fetch } from '@tauri-apps/plugin-http';const response = await fetch( 'https://raw.githubusercontent.com/tauri-apps/tauri/dev/package.json');use tauri_plugin_http::reqwest;
tauri::Builder::default() .plugin(tauri_plugin_http::init()) .setup(|app| { let response_data = tauri::async_runtime::block_on(async { let response = reqwest::get( "https://raw.githubusercontent.com/tauri-apps/tauri/dev/package.json", ) .await .unwrap(); response.text().await })?; Ok(()) })HTTP 插件重导出了 reqwest。所以你可以查阅它的文档以获取更多信息。
Rust 的 tauri::api::notification 和 JavaScript 的 @tauri-apps/api/notification API 被移除。使用 @tauri-apps/plugin-notification 插件作为替代:
- 添加 Cargo 依赖项:
[dependencies]tauri-plugin-notification = "2"- 在 JavaScript 或 Rust 项目中使用:
fn main() { tauri::Builder::default() .plugin(tauri_plugin_notification::init())}{ "dependencies": { "@tauri-apps/plugin-notification": "^2.0.0" }}import { sendNotification } from '@tauri-apps/plugin-notification';sendNotification('Tauri is awesome!');use tauri_plugin_notification::NotificationExt;use tauri::plugin::PermissionState;
fn main() { tauri::Builder::default() .plugin(tauri_plugin_notification::init()) .setup(|app| { if app.notification().permission_state()? == PermissionState::Unknown { app.notification().request_permission()?; } if app.notification().permission_state()? == PermissionState::Granted { app.notification() .builder() .body("Tauri is awesome!") .show()?; } Ok(()) })}Rust 的 Menu API 被移动到 tauri::menu 模块,并使用 muda crate 重构。
使用 tauri::menu::MenuBuilder 以替换 tauri::Menu。
注意到它的构造器接收一个 Manager 实例(App、AppHandle 或 WebviewWindow 中的一个)作为入参:
use tauri::menu::MenuBuilder;
tauri::Builder::default() .setup(|app| { let menu = MenuBuilder::new(app) .copy() .paste() .separator() .undo() .redo() .text("open-url", "Open URL") .check("toggle", "Toggle") .icon("show-app", "Show App", app.default_window_icon().cloned().unwrap()) .build()?; Ok(()) })使用 tauri::menu::PredefinedMenuItem 以替换 tauri::MenuItem:
use tauri::menu::{MenuBuilder, PredefinedMenuItem};
tauri::Builder::default() .setup(|app| { let menu = MenuBuilder::new(app).item(&PredefinedMenuItem::copy(app)?).build()?; Ok(()) })使用 tauri::menu::MenuItemBuilder 以替换 tauri::CustomMenuItem:
use tauri::menu::MenuItemBuilder;
tauri::Builder::default() .setup(|app| { let toggle = MenuItemBuilder::new("Toggle").accelerator("Ctrl+Shift+T").build(app)?; Ok(()) })使用 tauri::menu::SubmenuBuilder 以替换 tauri::Submenu:
use tauri::menu::{MenuBuilder, SubmenuBuilder};
tauri::Builder::default() .setup(|app| { let submenu = SubmenuBuilder::new(app, "Sub") .text("Tauri") .separator() .check("Is Awesome") .build()?; let menu = MenuBuilder::new(app).item(&submenu).build()?; Ok(()) })tauri::Builder::menu 现在接收一个闭包,因为菜单需要一个 Manager 实例来构造。参考相关文档以获取更多信息。
Rust 的 tauri::Builder::on_menu_event API 被移除。使用 tauri::App::on_menu_event 或 tauri::AppHandle::on_menu_event 作为替代:
use tauri::menu::{CheckMenuItemBuilder, MenuBuilder, MenuItemBuilder};
tauri::Builder::default() .setup(|app| { let toggle = MenuItemBuilder::with_id("toggle", "Toggle").build(app)?; let check = CheckMenuItemBuilder::new("Mark").build(app)?; let menu = MenuBuilder::new(app).items(&[&toggle, &check]).build()?;
app.set_menu(menu)?;
app.on_menu_event(move |app, event| { if event.id() == check.id() { println!("`check` triggered, do something! is checked? {}", check.is_checked().unwrap()); } else if event.id() == "toggle" { println!("toggle triggered!"); } }); Ok(()) })请注意,有两种方法可以检查哪个菜单项被选中:将项目移至事件处理程序闭包并比较 ID,或通过 with_id 构造函数为项目定义自定义 ID,并使用该 ID 字符串进行比较。
Rust 的 tauri::api::os 和 JavaScript 的 @tauri-apps/api/os API 被移除。使用 @tauri-apps/plugin-os 插件作为替代:
- 添加 Cargo 依赖项:
[dependencies]tauri-plugin-os = "2"- 在 JavaScript 或 Rust 项目中使用:
fn main() { tauri::Builder::default() .plugin(tauri_plugin_os::init())}{ "dependencies": { "@tauri-apps/plugin-os": "^2.0.0" }}import { arch } from '@tauri-apps/plugin-os';const architecture = await arch();fn main() { tauri::Builder::default() .plugin(tauri_plugin_os::init()) .setup(|app| { let os_arch = tauri_plugin_os::arch(); Ok(()) })}Rust 的 tauri::api::process 和 JavaScript 的 @tauri-apps/api/process API 被移除。使用 @tauri-apps/plugin-process 插件作为替代:
- 添加到 Cargo 依赖项:
[dependencies]tauri-plugin-process = "2"- 在 JavaScript 或 Rust 项目中使用:
fn main() { tauri::Builder::default() .plugin(tauri_plugin_process::init())}{ "dependencies": { "@tauri-apps/plugin-process": "^2.0.0" }}import { exit, relaunch } from '@tauri-apps/plugin-process';await exit(0);await relaunch();fn main() { tauri::Builder::default() .plugin(tauri_plugin_process::init()) .setup(|app| { // 以给定的状态码退出应用程序 app.handle().exit(1); // 重新启动应用程序 app.handle().restart(); Ok(()) })}Rust 的 tauri::api::shell 和 JavaScript 的 @tauri-apps/api/shell API 被移除。使用 @tauri-apps/plugin-shell 插件作为替代:
- 添加 Cargo 依赖项:
[dependencies]tauri-plugin-shell = "2"- 在 JavaScript 或 Rust 项目中使用:
fn main() { tauri::Builder::default() .plugin(tauri_plugin_shell::init())}{ "dependencies": { "@tauri-apps/plugin-shell": "^2.0.0" }}import { Command, open } from '@tauri-apps/plugin-shell';const output = await Command.create('echo', 'message').execute();
await open('https://github.com/tauri-apps/tauri');- 打开一个 URL:
use tauri_plugin_shell::ShellExt;
fn main() { tauri::Builder::default() .plugin(tauri_plugin_shell::init()) .setup(|app| { app.shell().open("https://github.com/tauri-apps/tauri", None)?; Ok(()) })}- 生成子进程并获取状态码:
use tauri_plugin_shell::ShellExt;
fn main() { tauri::Builder::default() .plugin(tauri_plugin_shell::init()) .setup(|app| { let status = tauri::async_runtime::block_on(async move { app.shell().command("which").args(["ls"]).status().await.unwrap() }); println!("`which` finished with status: {:?}", status.code()); Ok(()) })}- 生成子进程并捕获其输出:
use tauri_plugin_shell::ShellExt;
fn main() { tauri::Builder::default() .plugin(tauri_plugin_shell::init()) .setup(|app| { let output = tauri::async_runtime::block_on(async move { app.shell().command("echo").args(["TAURI"]).output().await.unwrap() }); assert!(output.status.success()); assert_eq!(String::from_utf8(output.stdout).unwrap(), "TAURI"); Ok(()) })}- 生成一个子进程并异步读取其事件:
use tauri_plugin_shell::{ShellExt, process::CommandEvent};
fn main() { tauri::Builder::default() .plugin(tauri_plugin_shell::init()) .setup(|app| { let handle = app.handle().clone(); tauri::async_runtime::spawn(async move { let (mut rx, mut child) = handle.shell().command("cargo") .args(["tauri", "dev"]) .spawn() .expect("Failed to spawn cargo");
let mut i = 0; while let Some(event) = rx.recv().await { if let CommandEvent::Stdout(line) = event { println!("got: {}", String::from_utf8(line).unwrap()); i += 1; if i == 4 { child.write("message from Rust\n".as_bytes()).unwrap(); i = 0; } } } }); Ok(()) })}Rust 的 SystemTray API 被重命名为 TrayIcon 以确保一致性。新的 API 可以在 Rust 的 tray 模块中找到。
使用 tauri::tray::TrayIconBuilder 以替换 tauri::SystemTray:
let tray = tauri::tray::TrayIconBuilder::with_id("my-tray").build(app)?;查阅 TrayIconBuilder 以获取更多信息。
使用 tauri::menu::Menu 以替换 tauri::SystemTrayMenu、tauri::menu::Submenu 以替换 tauri::SystemTraySubmenu 和 tauri::menu::PredefinedMenuItem 以替换 tauri::SystemTrayMenuItem。
tauri::SystemTray::on_event 被分割为 tauri::tray::TrayIconBuilder::on_menu_event 和 tauri::tray::TrayIconBuilder::on_tray_icon_event:
use tauri::{ menu::{MenuBuilder, MenuItemBuilder}, tray::{MouseButton, MouseButtonState, TrayIconBuilder, TrayIconEvent},};
tauri::Builder::default() .setup(|app| { let toggle = MenuItemBuilder::with_id("toggle", "Toggle").build(app)?; let menu = MenuBuilder::new(app).items(&[&toggle]).build()?; let tray = TrayIconBuilder::new() .menu(&menu) .on_menu_event(move |app, event| match event.id().as_ref() { "toggle" => { println!("toggle clicked"); } _ => (), }) .on_tray_icon_event(|tray, event| { if let TrayIconEvent::Click { button: MouseButton::Left, button_state: MouseButtonState::Up, .. } = event { let app = tray.app_handle(); if let Some(webview_window) = app.get_webview_window("main") { let _ = webview_window.unminimize(); let _ = webview_window.show(); let _ = webview_window.set_focus(); } } }) .build(app)?;
Ok(()) })内置的自动更新的提示窗被移除。作为代替,使用 Rust 和 JS API 以检查和安装更新。
Rust 的 tauri::updater 和 JavaScript 的 @tauri-apps/api-updater API 被移除。
使用 @tauri-apps/plugin-updater 设置一个自定义的更新器:
- 添加 Cargo 依赖项:
[dependencies]tauri-plugin-updater = "2"- 在 JavaScript 或 Rust 项目中使用:
fn main() { tauri::Builder::default() .plugin(tauri_plugin_updater::Builder::new().build())}{ "dependencies": { "@tauri-apps/plugin-updater": "^2.0.0" }}import { check } from '@tauri-apps/plugin-updater';import { relaunch } from '@tauri-apps/plugin-process';
const update = await check();if (update?.available) { console.log(`Update to ${update.version} available! Date: ${update.date}`); console.log(`Release notes: ${update.body}`); await update.downloadAndInstall(); // 需要 `process` 插件 await relaunch();}检查更新:
use tauri_plugin_updater::UpdaterExt;
fn main() { tauri::Builder::default() .plugin(tauri_plugin_updater::Builder::new().build()) .setup(|app| { let handle = app.handle(); tauri::async_runtime::spawn(async move { let response = handle.updater().check().await; }); Ok(()) })}设置自定义更新目标:
fn main() { let mut updater = tauri_plugin_updater::Builder::new(); #[cfg(target_os = "macos")] { updater = updater.target("darwin-universal"); } tauri::Builder::default() .plugin(updater.build())}Rust 的 tauri::api::path 模块的函数和 tauri::PathResolver 被移动到 tauri::Manager::path:
use tauri::{path::BaseDirectory, Manager};
tauri::Builder::default() .setup(|app| { let home_dir_path = app.path().home_dir().expect("failed to get home dir");
let path = app.path().resolve("path/to/something", BaseDirectory::Config)?;
Ok(()) })在 Rust 侧,Window 被重命名为 WebviewWindow,它的构建器 WindowBuilder 被重命名为 WebviewWindowBuilder。
另外,Manager::get_window 函数被重命名为 get_webview_window,窗口的 parent_window API 被重命名为 parent_raw 以支持高级窗口父 API。
在 JavaScript 侧,WebviewWindow 类现在从 @tauri-apps/api/webviewWindow 中重导出。
onMenuClicked 函数已被移除。你可以在 JavaScript 中创建菜单时拦截菜单事件。
在 JavaScript 侧,请确保迁移文件系统插件。
此外,请注意迁移授权许可中对 v1 的授权许可列表所作的更改。
在 Rust 侧,请确保将 Path 迁移到 Tauri Manager.
在 Tauri v1 中,外部的二进制文件和其参数在许可列表中被定义。而在 v2 中,使用了新的权限系统。有关详细信息,请阅读迁移授权许可。
在 JavaScript 侧,请确保迁移 Shell 插件。
在 Rust 侧,tauri::api::process API 已经被移除,使用 tauri_plugin_shell::ShellExt 和 tauri_plugin_shell::process::CommandEvent 作为替代。嵌入的外部二进制文档将指导你如何迁移。
在 v2 中移除了 “process-command-api” 特性。因此,运行外部的二进制文件不需要再在 Tauri 配置文件中配置。
授权许可列表 v1 已被重写为一个全新的权限系统,可用于单个插件,并可为多窗口和远程 URL 支持进行更多配置。 这个新系统的工作原理类似于访问控制列表(ACL),你可以允许或拒绝命令、将权限分配给一组特定的窗口和域,并定义访问范围。
要为应用程序启用权限,您必须在 src-tauri/capabilities 文件夹内创建许可配置文件,随后 Tauri 会自动为您配置其他一切。
migrate 命令行工具命令会自动解析你的授权许可列表 v1 并生成相关的许可配置文件。
要了解有关权限和功能的更多信息,请参阅安全文档。
© 2025 Tauri Contributors. CC-BY / MIT