Upgrade from Tauri 1.0
This guide walks you through upgrading your Tauri 1.0 application to Tauri 2.0.
Preparing for Mobile
The mobile interface of Tauri requires your project to output a shared library. If you are targetting mobile for your existing application, you must change your crate to produce that kind of artifact along with the desktop executable.
- Change the Cargo manifest to produce the library. Append the following block:
[lib]name = "app_lib"crate-type = ["staticlib", "cdylib", "rlib"]-
Rename
src-tauri/src/main.rstosrc-tauri/src/lib.rs. This file will be shared by both desktop and mobile targets. -
Rename the
mainfunction header inlib.rsto the following:
#[cfg_attr(mobile, tauri::mobile_entry_point)]pub fn run() { // your code here}The tauri::mobile_entry_point macro prepares your function to be executed on mobile.
- Recreate the
main.rsfile calling the shared run function:
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
fn main() { app_lib::run();}Automated Migration
The Tauri v2 CLI includes a migrate command that automates most of the process and helps you finish the migration:
npm install @tauri-apps/cli@nextnpm run tauri migrateyarn upgrade @tauri-apps/cli --nextyarn tauri migratepnpm update @tauri-apps/cli@nextpnpm tauri migratecargo install tauri-cli --version "^2.0.0-beta"cargo tauri migrateLearn more about the migrate command in the Command Line Interface reference
Summary of Changes
Below is a summary of the changes from Tauri 1.0 to Tauri 2.0:
Tauri Configuration
package > productNameandpackage > versionmoved to top-level field.packageremoved.taurikey renamed toapp.tauri > allowlistremoved. Refer to Migrate Permissions.tauri > allowlist > protocol > assetScopemoved toapp > security > assetProtocol > scope.tauri > climoved toplugins > cli.tauri > windows > fileDropEnabledrenamed toapp > windows > dragDropEnabled.tauri > updater > activeremoved.tauri > updater > dialogremoved.tauri > updatermoved toplugins > updater.tauri > systemTrayrenamed toapp > trayIcon.tauri > patternmoved toapp > security > pattern.tauri > bundlemoved top-level.tauri > bundle > dmgmoved tobundle > macOS > dmgtauri > bundle > debmoved tobundle > linux > debtauri > bundle > appimagemoved tobundle > linux > appimagetauri > bundle > macOS > licenseremoved, usebundle > licenseFileinstead.tauri > bundle > windows > wix > licenseremoved, usebundle > licenseFileinstead.tauri > bundle > windows > nsis > licenseremoved, usebundle > licenseFileinstead.build > withGlobalTaurimoved toapp > withGlobalTauri.build > distDirrenamed tofrontendDist.build > devPathrenamed todevUrl.
Tauri 2.0 Configuration API reference
New Cargo Features
- linux-protocol-body: Enables custom protocol request body parsing, allowing the IPC to use it. Requires webkit2gtk 2.40.
Removed Cargo Features
- reqwest-client: reqwest is now the only supported client.
- reqwest-native-tls-vendored: use
native-tls-vendoredinstead. - process-command-api: use the
shellplugin instead (see instructions in the following section). - shell-open-api: use the
shellplugin instead (see instructions in the following section). - windows7-compat: moved to the
notificationplugin. - updater: Updater is now a plugin.
- linux-protocol-headers: Now enabled by default since we upgraded our minimum webkit2gtk version.
- system-tray: renamed to
tray-icon.
Rust Crate Changes
apimodule removed. Each API module can be found in a Tauri plugin.api::dialogmodule removed. Usetauri-plugin-dialoginstead. Migrationapi::filemodule removed. Use Rust’sstd::fsinstead.api::httpmodule removed. Usetauri-plugin-httpinstead. Migrationapi::ipmodule rewritten and moved totauri::ipc. Check out the new APIs, speciallytauri::ipc::Channel.api::pathmodule functions andtauri::PathResolvedmoved totauri::Manager::path. Migrationapi::process::Command,tauri::api::shellandtauri::Manager::shell_scopeAPIs removed. Usetauri-plugin-shellinstead. Migrationapi::process::current_binaryandtauri::api::process::restartmoved totauri::process.api::versionmodule has been removed. Use the semver crate instead.App::clipboard_managerandAppHandle::clipboard_managerremoved. Usetauri-plugin-clipboardinstead. MigrationApp::get_cli_matchesremoved. Usetauri-plugin-cliinstead. MigrationApp::global_shortcut_managerandAppHandle::global_shortcut_managerremoved. Usetauri-plugin-global-shortcutinstead. MigrationManager::fs_scoperemoved. The file system scope can be accessed viatauri_plugin_fs::FsExt.Plugin::PluginApinow receives a plugin configuration as a second argument.Plugin::setup_with_configremoved. Use the updatedtauri::Plugin::PluginApiinstead.scope::ipc::RemoteDomainAccessScope::enable_tauri_apiandscope::ipc::RemoteDomainAccessScope::enables_tauri_apiremoved. Enable each core plugin individually viascope::ipc::RemoteDomainAccessScope::add_plugininstead.scope::IpcScoperemoved, usescope::ipc::Scopeinstead.scope::IpcScoperemoved, usescope::ipc::Scopeinstead.scope::FsScope,scope::GlobPatternandscope::FsScopeEventremoved, usescope::fs::Scope,scope::fs::Patternandscope::fs::Eventrespectively.updatermodule removed. Usetauri-plugin-updaterinstead. MigrationEnv.argsfield has been removed, useEnv.args_osfield instead.Menu,MenuEvent,CustomMenuItem,Submenu,WindowMenuEvent,MenuItemandBuilder::on_menu_eventAPIs removed. MigrationSystemTray,SystemTrayHandle,SystemTrayMenu,SystemTrayMenuItemHandle,SystemTraySubmenu,MenuEntryandSystemTrayMenuItemAPIs removed. Migration
JavaScript API Changes
The @tauri-apps/api package no longer provides non-core modules. Only the previous tauri (now core), path, event and window modules are exported. All others have been moved to plugins.
@tauri-apps/api/taurimodule renamed to@tauri-apps/api/core. Migration@tauri-apps/api/climodule removed. Use@tauri-apps/plugin-cliinstead. Migration@tauri-apps/api/clipboardmodule removed. Use@tauri-apps/plugin-clipboardinstead. Migration@tauri-apps/api/dialogmodule removed. Use@tauri-apps/plugin-dialoginstead. Migration@tauri-apps/api/fsmodule removed. Use@tauri-apps/plugin-fsinstead. Migration@tauri-apps/api/global-shortcutmodule removed. Use@tauri-apps/plugin-global-shortcutinstead. Migration@tauri-apps/api/httpmodule removed. Use@tauri-apps/plugin-httpinstead. Migration@tauri-apps/api/osmodule removed. Use@tauri-apps/plugin-osinstead. Migration@tauri-apps/api/notificationmodule removed. Use@tauri-apps/plugin-notificationinstead. Migration@tauri-apps/api/processmodule removed. Use@tauri-apps/plugin-processinstead. Migration@tauri-apps/api/shellmodule removed. Use@tauri-apps/plugin-shellinstead. Migration@tauri-apps/api/updatermodule removed. Use@tauri-apps/plugin-updaterinstead Migration@tauri-apps/api/windowmodule renamed to@tauri-apps/api/webviewWindow. Migration
Environment Variables Changes
Most of the environment variables read and written by the Tauri CLI were renamed for consistency and prevention of mistakes:
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
Event System
The event system was redesigned to be easier to use. Instead of relying on the source of the event, it now has a simpler implementation that relies on event targets.
- The
emitfunction now emits the event to all event listeners - Added a new
emit_tofunction to trigger an event to a specific target emit_filternow filters based onEventTargetinstead of a window.- Renamed
listen_globaltolisten_any. It now listens to all events regardless of their filters and targets.
Multiwebview support
Tauri v2 introduces multiwebview support currently behind an unstable feature flag.
In order to support it, we renamed the Rust Window type to WebviewWindow and the Manager get_window function to get_webview_window.
The WebviewWindow JS API type is now re-exported from @tauri-apps/api/webviewWindow instead of @tauri-apps/api/window.
Detailed Migration Steps
Common scenarios you may encounter when migrating your Tauri 1.0 app to Tauri 2.0.
Migrate to Core Module
The @tauri-apps/api/tauri module was renamed to @tauri-apps/api/core.
Simply rename the module import:
import { invoke } from "@tauri-apps/api/tauri"import { invoke } from "@tauri-apps/api/core"Migrate to CLI Plugin
The Rust App::get_cli_matches JavaScript @tauri-apps/api/cli APIs have been removed. Use the @tauri-apps/plugin-cli plugin instead:
- Add to cargo dependencies:
[dependencies]tauri-plugin-cli = "2"- Use in JavaScript or Rust project:
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(()) })}Migrate to Clipboard Plugin
The Rust App::clipboard_manager and AppHandle::clipboard_manager and JavaScript @tauri-apps/api/clipboard APIs have been removed. Use the @tauri-apps/plugin-clipboard-manager plugin instead:
[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(()) })Migrate to Dialog Plugin
The Rust tauri::api::dialog JavaScript @tauri-apps/api/dialog APIs have been removed. Use the @tauri-apps/plugin-dialog plugin instead:
- Add to cargo dependencies:
[dependencies]tauri-plugin-dialog = "2"- Use in JavaScript or Rust project:
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| { // do something with the optional file path here // the file path is `None` if the user closed the dialog });
app.dialog().message("Tauri is Awesome!").show(); Ok(()) })Migrate to File System Plugin
The Rust App::get_cli_matches JavaScript @tauri-apps/api/fs APIs have been removed. Use the std::fs for Rust and @tauri-apps/plugin-fs plugin for JavaScript instead:
- Add to cargo dependencies:
[dependencies]tauri-plugin-fs = "2"- Use in JavaScript or Rust project:
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 });Some functions and types have been renamed or removed:
Direnum alias removed, useBaseDirectory.FileEntry,FsBinaryFileOption,FsDirOptions,FsOptions,FsTextFileOptionandBinaryFileContentsinterfaces and type aliases have been removed and replaced with new interfaces suited for each function.createDirrenamed tomkdir.readBinaryFilerenamed toreadFile.removeDirremoved and replaced withremove.removeFileremoved and replaced withremove.renameFileremoved and replaced withrename.writeBinaryFilerenamed towriteFile.
Use the Rust std::fs functions.
Migrate to Global Shortcut Plugin
The Rust App::global_shortcut_manager and AppHandle::global_shortcut_manager and JavaScript @tauri-apps/api/global-shortcut APIs have been removed. Use the @tauri-apps/plugin-global-shortcut plugin instead:
- Add to cargo dependencies:
[dependencies][target."cfg(not(any(target_os = \"android\", target_os = \"ios\")))".dependencies]tauri-plugin-global-shortcut = "2"- Use in JavaScript or Rust project:
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::with_handler(|app, shortcut| { println!("Shortcut triggered: {:?}", shortcut); }) .build(), ) .setup(|app| { // register a global shortcut // on macOS, the Cmd key is used // on Windows and Linux, the Ctrl key is used app.global_shortcut().register("CmdOrCtrl+Y")?; Ok(()) })Migrate to HTTP Plugin
The Rust tauri::api::http JavaScript @tauri-apps/api/http APIs have been removed. Use the @tauri-apps/plugin-http plugin instead:
- Add to cargo dependencies:
[dependencies]tauri-plugin-http = "2"- Use in JavaScript or Rust project:
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_dialog::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(()) })The HTTP plugin re-exports reqwest so you can check out their documentation for more information.
Migrate to Notification Plugin
The Rust tauri::api::notification JavaScript @tauri-apps/api/notification APIs have been removed. Use the @tauri-apps/plugin-notification plugin instead:
- Add to cargo dependencies:
[dependencies]tauri-plugin-notification = "2"- Use in JavaScript or Rust project:
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, 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(()) })}Migrate to Menu Module
The Rust Menu APIs were moved to the tauri::menu module and refactored to use the muda crate.
Use tauri::menu::MenuBuilder
Use tauri::menu::MenuBuilder instead of tauri::Menu. Note that its constructor takes a Manager instance (one of App, AppHandle or WebviewWindow) as an argument:
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(()) })Use tauri::menu::PredefinedMenuItem
Use tauri::menu::PredefinedMenuItem instead of tauri::MenuItem:
use tauri::menu::{MenuBuilder, PredefinedMenuItem};
tauri::Builder::default() .setup(|app| { let menu = MenuBuilder::new(app).item(&PredefinedMenuItem::copy(app)?).build()?; Ok(()) })Use tauri::menu::MenuItemBuilder
Use tauri::menu::MenuItemBuilder instead of tauri::CustomMenuItem:
use tauri::menu::MenuItemBuilder;
tauri::Builder::default() .setup(|app| { let toggle = MenuItemBuilder::new("Toggle").accelerator("Ctrl+Shift+T").build(app)?; Ok(()) })Use tauri::menu::SubmenuBuilder
Use tauri::menu::SubmenuBuilder instead of 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 now takes a closure because the menu needs a Manager instance to be built. See the documentation for more information.
Menu Events
The Rust tauri::Builder::on_menu_event API was removed. Use tauri::App::on_menu_event or tauri::AppHandle::on_menu_event instead:
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(()) })Note that there are two ways to check which menu item was selected: move the item to the event handler closure and compare IDs, or define a custom ID for the item through the with_id constructor and use that ID string to compare.
Migrate to OS Plugin
The Rust tauri::api::os JavaScript @tauri-apps/api/os APIs have been removed. Use the @tauri-apps/plugin-os plugin instead:
- Add to cargo dependencies:
[dependencies]tauri-plugin-os = "2"- Use in JavaScript or Rust project:
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(()) })}Migrate to Process Plugin
The Rust tauri::api::process JavaScript @tauri-apps/api/process APIs have been removed. Use the @tauri-apps/plugin-process plugin instead:
- Add to cargo dependencies:
[dependencies]tauri-plugin-process = "2"- Use in JavaScript or Rust project:
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| { // exit the app with a status code app.handle().exit(1); // restart the app app.handle().restart(); Ok(()) })}Migrate to Shell Plugin
The Rust tauri::api::shell JavaScript @tauri-apps/api/shell APIs have been removed. Use the @tauri-apps/plugin-shell plugin instead:
- Add to cargo dependencies:
[dependencies]tauri-plugin-shell = "2"- Use in JavaScript or Rust project:
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');- Open an 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(()) })}- Spawn a child process and retrieve the status code
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(()) })}- Spawn a child process and capture its output
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(()) })}- Spawn a child process and read its events asynchronously:
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(()) })}Migrate to Tray Icon Module
The Rust SystemTray APIs were renamed to TrayIcon for consistency. The new APIs can be found in the Rust tray module.
Use tauri::tray::TrayIconBuilder
Use tauri::tray::TrayIconBuilder instead of tauri::SystemTray:
let tray = tauri::tray::TrayIconBuilder::with_id("my-tray").build(app)?;See TrayIconBuilder for more information.
Migrate to Menu
Use tauri::menu::Menu instead of tauri::SystemTrayMenu, tauri::menu::Submenu instead of tauri::SystemTraySubmenu and tauri::menu::PredefinedMenuItem instead of tauri::SystemTrayMenuItem. Migration
Tray Events
tauri::SystemTray::on_event have been split into tauri::tray::TrayIconBuilder::on_menu_event and 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.show(); let _ = webview_window.set_focus(); } } }) .build(app)?;
Ok(()) })Migrate to Updater Plugin
The built-in dialog with an automatic update check was removed, use the Rust and JS APIs to check for and install updates instead.
The Rust tauri::updater and JavaScript @tauri-apps/api-updater APIs have been removed. To set a custom updater target with the @tauri-apps/plugin-updater:
- Add to cargo dependencies:
[dependencies]tauri-plugin-updater = "2"- Use in JavaScript of Rust project:
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(); // requires the `process` plugin await relaunch();}To check for updates:
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(()) })}To set a custom updater target:
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())}Migrate Path to Tauri Manager
The Rust tauri::api::path module functions and tauri::PathResolver have been moved to 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(()) })Migrate to new Window API
On the Rust side, Window was renamed to WebviewWindow and its builder WindowBuilder is now named WebviewWindowBuilder.
Additionally, the Manager::get_window function was renamed to get_webview_window and
the window’s parent_window API was renamed to parent_raw to support a high level window parent API.
On the JavaScript side, the WebviewWindow class is now exported in the @tauri-apps/api/webviewWindow path.
The onMenuClicked function was removed, you can intercept menu events when creating a menu in JavaScript instead.
Migrate Embedded Additional Files (Resources)
On the JavaScript side, make sure you Migrate to File System Plugin. Additionally, note the changes made to the v1 allowlist in Migrate Permissions.
On the Rust side, make sure you Migrate Path to Tauri Manager.
Migrate Embedded External Binaries (Sidecar)
In Tauri v1, the external binaries and their arguments were defined in the allowlist. In v2, use the new permissions system. Read Migrate Permissions for more information.
On the JavaScript side, make sure you Migrate to Shell Plugin.
On the Rust side, tauri::api::process API has been removed. Use tauri_plugin_shell::ShellExt and tauri_plugin_shell::process::CommandEvent APIs instead. Read the Embedding External Binaries guide to see how.
The “process-command-api” features flag has been removed in v2. So running the external binaries does not require this feature to be defined in the Tauri config anymore.
Migrate Permissions
The v1 allowlist have been rewritten to a completely new system for permissions that works for individual plugins and is much more configurable for multiwindow and remote URL support. This new system works like an access control list (ACL) where you can allow or deny commands, allocate permissions to a specific set of windows and domains, and define access scopes.
To enable permissions for your app, you must create capability files inside the src-tauri/capabilities folder, and Tauri will automatically configure everything else for you.
The migrate CLI command automatically parses your v1 allowlist and generates the associated capability file.
To learn more about permissions and capabilities, see the security documentation.
© 2024 Tauri Contributors. CC-BY / MIT