更新程序
使用更新服务器或静态 JSON 自动更新你的 Tauri 应用。
🌐 Automatically update your Tauri app with an update server or a static JSON.
🌐 Supported Platforms
This plugin requires a Rust version of at least 1.77.2
| Platform | Level | Notes |
|---|---|---|
| windows | ||
| linux | ||
| macos | ||
| android | | |
| ios | |
🌐 Setup
安装 Tauri 更新程序插件以开始使用。
🌐 Install the Tauri updater plugin to get started.
使用项目的包管理器添加依赖:
npm run tauri add updateryarn run tauri add updaterpnpm tauri add updaterdeno task tauri add updaterbun tauri add updatercargo tauri add updater-
在
src-tauri文件夹中运行以下命令,将插件添加到Cargo.toml中的项目依赖:cargo add tauri-plugin-updater --target 'cfg(any(target_os = "macos", windows, target_os = "linux"))' -
修改
lib.rs以初始化插件:lib.rs #[cfg_attr(mobile, tauri::mobile_entry_point)]pub fn run() {tauri::Builder::default().setup(|app| {#[cfg(desktop)]app.handle().plugin(tauri_plugin_updater::Builder::new().build());Ok(())}).run(tauri::generate_context!()).expect("error while running tauri application");} -
你可以使用你喜欢的 JavaScript 包管理器安装 JavaScript 客户端绑定:
npm install @tauri-apps/plugin-updateryarn add @tauri-apps/plugin-updaterpnpm add @tauri-apps/plugin-updaterdeno add npm:@tauri-apps/plugin-updaterbun add @tauri-apps/plugin-updater
🌐 Signing updates
Tauri 的更新程序需要一个签名来验证更新是否来自可信来源。这无法被禁用。
🌐 Tauri’s updater needs a signature to verify that the update is from a trusted source. This cannot be disabled.
要签署更新,你需要两个密钥:
🌐 To sign your updates you need two keys:
- 公钥将设置在
tauri.conf.json中,以在安装前验证工件。只要你的私钥安全,这个公钥可以安全地上传和共享。 - 私钥用于签署你的安装程序文件。你绝对不应与任何人分享此密钥。此外,如果你丢失此密钥,你将无法向已经安装了应用的用户发布新的更新。将此密钥存放在安全的地方非常重要!
要生成密钥,Tauri CLI 提供了 signer generate 命令。你可以运行此命令在主目录中创建密钥:
🌐 To generate the keys the Tauri CLI provides the signer generate command. You can run this to create the keys in the home folder:
npm run tauri signer generate -- -w ~/.tauri/myapp.keyyarn tauri signer generate -w ~/.tauri/myapp.keypnpm tauri signer generate -w ~/.tauri/myapp.keydeno task tauri signer generate -w ~/.tauri/myapp.keybunx tauri signer generate -w ~/.tauri/myapp.keycargo tauri signer generate -w ~/.tauri/myapp.key🌐 Building
在构建更新工件时,你需要在环境变量中拥有上述生成的私钥。.env 文件是 不 可用的!
🌐 While building your update artifacts, you need to have the private key you generated above in your environment variables. .env files do not work!
export TAURI_SIGNING_PRIVATE_KEY="Path or content of your private key"# optionally also add a passwordexport TAURI_SIGNING_PRIVATE_KEY_PASSWORD=""Run this in PowerShell:
$env:TAURI_SIGNING_PRIVATE_KEY="Path or content of your private key"<# optionally also add a password #>$env:TAURI_SIGNING_PRIVATE_KEY_PASSWORD=""之后,你可以像往常一样运行 Tauri 构建,Tauri 将生成更新包及其签名。
生成的文件取决于下面配置的 createUpdaterArtifacts 配置值。
🌐 After that, you can run Tauri build as usual and Tauri will generate the update bundles and their signatures.
The generated files depend on the createUpdaterArtifacts configuration value configured below.
{ "bundle": { "createUpdaterArtifacts": true }}在 Linux 上,Tauri 会在 target/release/bundle/appimage/ 文件夹内创建普通的 AppImage:
🌐 On Linux, Tauri will create the normal AppImage inside the target/release/bundle/appimage/ folder:
myapp.AppImage- 标准应用包。它将被更新程序重复使用。myapp.AppImage.sig- 更新程序包的签名。
在 macOS 上,Tauri 将从 target/release/bundle/macos/ 文件夹中的应用包中创建一个 .tar.gz 存档:
🌐 On macOS, Tauri will create a .tar.gz archive from the application bundle inside the target/release/bundle/macos/ folder:
myapp.app- 标准应用包。myapp.app.tar.gz- 更新程序包。myapp.app.tar.gz.sig- 更新包的签名。
在 Windows 上,Tauri 将在 target/release/bundle/msi/ 和 target/release/bundle/nsis 文件夹内创建常规 MSI 和 NSIS 安装程序:
🌐 On Windows, Tauri will create the normal MSI and NSIS installers inside the target/release/bundle/msi/ and target/release/bundle/nsis folders:
myapp-setup.exe- 标准应用包。它将被更新程序重复使用。myapp-setup.exe.sig- 更新包的签名。myapp.msi- 标准应用包。它将被更新程序重复使用。myapp.msi.sig- 更新包的签名。
{ "bundle": { "createUpdaterArtifacts": "v1Compatible" }}在 Linux 上,Tauri 会从 target/release/bundle/appimage/ 文件夹内的 AppImage 创建一个 .tar.gz 压缩包:
🌐 On Linux, Tauri will create a .tar.gz archive from the AppImage inside the target/release/bundle/appimage/ folder:
myapp.AppImage- 标准应用包。myapp.AppImage.tar.gz- 更新程序包。myapp.AppImage.tar.gz.sig- 更新包的签名。
在 macOS 上,Tauri 将从 target/release/bundle/macos/ 文件夹中的应用包中创建一个 .tar.gz 存档:
🌐 On macOS, Tauri will create a .tar.gz archive from the application bundle inside the target/release/bundle/macos/ folder:
myapp.app- 标准应用包。myapp.app.tar.gz- 更新程序包。myapp.app.tar.gz.sig- 更新包的签名。
在 Windows 上,Tauri 将从 target/release/bundle/msi/ 和 target/release/bundle/nsis 文件夹内的 MSI 和 NSIS 安装程序创建 .zip 存档:
🌐 On Windows, Tauri will create .zip archives from the MSI and NSIS installers inside the target/release/bundle/msi/ and target/release/bundle/nsis folders:
myapp-setup.exe- 标准应用包。myapp-setup.nsis.zip- 更新程序包。myapp-setup.nsis.zip.sig- 更新包的签名。myapp.msi- 标准应用包。myapp.msi.zip- 更新程序包。myapp.msi.zip.sig- 更新包的签名。
🌐 Tauri Configuration
以此格式设置 tauri.conf.json,以便更新程序开始工作。
🌐 Set up the tauri.conf.json in this format for the updater to start working.
| 键 | 描述 |
|---|---|
createUpdaterArtifacts | 将此设置为 true 会告诉 Tauri 的应用打包工具创建更新器工件。如果你正在将应用从旧版本 Tauri 迁移,请改为设置为 "v1Compatible"。此设置将在 v3 中移除,所以确保在所有用户迁移到 v2 后将其更改为 true。 |
pubkey | 这必须是上一步通过 Tauri CLI 生成的公钥。不能是文件路径! |
endpoints | 这必须是一个字符串数组,包含端点 URL。在生产模式下会强制使用 TLS。如果返回非 2XX 状态码,Tauri 才会继续尝试下一个 URL! |
dangerousInsecureTransportProtocol | 将此设置为 true 允许更新器接受非 HTTPS 端点。请谨慎使用此配置! |
每个更新程序 URL 可以包含以下动态变量,允许你在服务器端确定是否有可用的更新。
🌐 Each updater URL can contain the following dynamic variables, allowing you to determine server-side if an update is available.
{{current_version}}:请求更新的应用的版本。{{target}}:操作系统名称(linux、windows或darwin之一)。{{arch}}:机器的架构(x86_64、i686、aarch64或armv7之一)。
{ "bundle": { "createUpdaterArtifacts": true }, "plugins": { "updater": { "pubkey": "CONTENT FROM PUBLICKEY.PEM", "endpoints": [ "https://releases.myapp.com/{{target}}/{{arch}}/{{current_version}}", // or a static github json file "https://github.com/user/repo/releases/latest/download/latest.json" ] } }}🌐 installMode on Windows
在 Windows 上,还有一个可选的 "installMode" 配置,用于更改更新的安装方式。
🌐 On Windows there is an additional optional "installMode" config to change how the update is installed.
{ "plugins": { "updater": { "windows": { "installMode": "passive" } } }}"passive":将会出现一个带有进度条的小窗口。更新将在无需任何用户操作的情况下安装。通常推荐,并且是默认模式。"basicUi":将显示一个基本用户界面,需要用户交互才能完成安装。"quiet":不会向用户提供进度反馈。在此模式下,安装程序无法自行请求管理员权限,因此它仅适用于全用户安装或当你的应用本身已经以管理员权限运行时。通常不推荐使用。
🌐 Server Support
更新插件可以用两种方式使用。可以通过动态更新服务器,或者使用静态 JSON 文件(用于像 S3 或 GitHub gists 这样的服务)。
🌐 The updater plugin can be used in two ways. Either with a dynamic update server or a static JSON file (to use on services like S3 or GitHub gists).
🌐 Static JSON File
当使用静态时,你只需返回包含所需信息的 JSON。
🌐 When using static, you just need to return a JSON containing the required information.
| 键 | 描述 |
|---|---|
version | 必须是有效的 SemVer,可以有或没有前导的 v,这意味着 1.0.0 和 v1.0.0 都是有效的。 |
notes | 更新的备注。 |
pub_date | 如果存在,日期必须按照 RFC 3339 格式化。 |
platforms | 每个平台键的格式为 OS-ARCH,其中 OS 是 linux、darwin 或 windows 之一,ARCH 是 x86_64、aarch64、i686 或 armv7 之一。 |
signature | 生成的 .sig 文件的内容,每次构建可能会发生变化。路径或 URL 无效! |
必需的键是 "version"、"platforms.[target].url" 和 "platforms.[target].signature"; 其他的是可选的。
🌐 The required keys are "version", "platforms.[target].url" and "platforms.[target].signature"; the others are optional.
{ "version": "", "notes": "", "pub_date": "", "platforms": { "linux-x86_64": { "signature": "", "url": "" }, "windows-x86_64": { "signature": "", "url": "" }, "darwin-x86_64": { "signature": "", "url": "" } }}请注意,Tauri 将在检查版本字段之前验证整个文件,因此请确保所有现有平台配置均有效且完整。
🌐 Note that Tauri will validate the whole file before checking the version field, so make sure all existing platform configurations are valid and complete.
🌐 Dynamic Update Server
在使用动态更新服务器时,Tauri 将遵循服务器的指示。要禁用内部版本检查,你可以覆盖插件的版本比较,这将安装服务器发送的版本(如果需要回滚应用,这很有用)。
🌐 When using a dynamic update server, Tauri will follow the server’s instructions. To disable the internal version check you can overwrite the plugin’s version comparison, this will install the version sent by the server (useful if you need to roll back your app).
你的服务器可以使用上面 endpoint URL 中定义的变量来确定是否需要更新。如果你需要更多数据,可以根据需要在 Rust 中包含额外的 请求头。
🌐 Your server can use variables defined in the endpoint URL above to determine if an update is required. If you need more data, you can include additional request headers in Rust to your liking.
如果没有可用更新,你的服务器应响应状态码204 No Content。
🌐 Your server should respond with a status code of 204 No Content if there is no update available.
如果需要更新,你的服务器应返回状态码 200 OK 并提供以下格式的 JSON 响应:
🌐 If an update is required, your server should respond with a status code of 200 OK and a JSON response in this format:
| 键 | 描述 |
|---|---|
version | 这必须是一个有效的 SemVer,可以有或没有前导的 v,意味着 1.0.0 和 v1.0.0 都是有效的。 |
notes | 关于更新的说明。 |
pub_date | 如果存在,日期必须按照 RFC 3339 格式。 |
url | 这必须是更新包的有效 URL。 |
signature | 生成的 .sig 文件的内容,每次构建可能会变化。路径或 URL 无效! |
所需的键是 "url"、"version" 和 "signature"; 其他的是可选的。
🌐 The required keys are "url", "version" and "signature"; the others are optional.
{ "version": "", "pub_date": "", "url": "", "signature": "", "notes": ""}🌐 Checking for Updates
用于检查更新和安装更新的默认 API 利用已配置的端点,并且可以被 JavaScript 和 Rust 代码访问。
🌐 The default API for checking updates and installing them leverages the configured endpoints and can be accessed by both JavaScript and Rust code.
import { check } from '@tauri-apps/plugin-updater';import { relaunch } from '@tauri-apps/plugin-process';
const update = await check();if (update) { console.log( `found update ${update.version} from ${update.date} with notes ${update.body}` ); let downloaded = 0; let contentLength = 0; // alternatively we could also call update.download() and update.install() separately await update.downloadAndInstall((event) => { switch (event.event) { case 'Started': contentLength = event.data.contentLength; console.log(`started downloading ${event.data.contentLength} bytes`); break; case 'Progress': downloaded += event.data.chunkLength; console.log(`downloaded ${downloaded} from ${contentLength}`); break; case 'Finished': console.log('download finished'); break; } });
console.log('update installed'); await relaunch();}有关更多信息,请参见 [JavaScript API 文档]。
🌐 For more information see the JavaScript API documentation.
use tauri_plugin_updater::UpdaterExt;
pub fn run() { tauri::Builder::default() .setup(|app| { let handle = app.handle().clone(); tauri::async_runtime::spawn(async move { update(handle).await.unwrap(); }); Ok(()) }) .run(tauri::generate_context!()) .unwrap();}
async fn update(app: tauri::AppHandle) -> tauri_plugin_updater::Result<()> { if let Some(update) = app.updater()?.check().await? { let mut downloaded = 0;
// alternatively we could also call update.download() and update.install() separately update .download_and_install( |chunk_length, content_length| { downloaded += chunk_length; println!("downloaded {downloaded} from {content_length:?}"); }, || { println!("download finished"); }, ) .await?;
println!("update installed"); app.restart(); }
Ok(())}更多信息请参阅 [Rust API 文档]。
🌐 For more information see the Rust API documentation.
请注意,在安装更新后立即重新启动你的应用并不是必须的,你可以选择如何处理更新,要么等待用户手动重新启动应用,要么提示他们选择何时进行。
🌐 Note that restarting your app immediately after installing an update is not required and you can choose how to handle the update by either waiting until the user manually restarts the app, or prompting them to select when to do so.
检查和下载更新时,可以定义自定义请求超时、代理和请求标头。
🌐 When checking and downloading updates it is possible to define a custom request timeout, a proxy and request headers.
import { check } from '@tauri-apps/plugin-updater';
const update = await check({ proxy: '<proxy url>', timeout: 30000 /* milliseconds */, headers: { Authorization: 'Bearer <token>', },});use tauri_plugin_updater::UpdaterExt;let update = app .updater_builder() .timeout(std::time::Duration::from_secs(30)) .proxy("<proxy-url>".parse().expect("invalid URL")) .header("Authorization", "Bearer <token>") .build()? .check() .await?;🌐 Runtime Configuration
更新程序 API 还允许在运行时配置更新程序,以获得更多的灵活性。出于安全原因,某些 API 仅对 Rust 可用。
🌐 The updater APIs also allows the updater to be configured at runtime for more flexibility. For security reasons some APIs are only available for Rust.
🌐 Endpoints
设置在运行时应请求以检查更新的 URL 允许更动态的更新,例如单独的发布渠道:
🌐 Setting the URLs that should be requested to check updates at runtime allows more dynamic updates such as separate release channels:
use tauri_plugin_updater::UpdaterExt;let channel = if beta { "beta" } else { "stable" };let update_url = format!("https://{channel}.myserver.com/{{{{target}}}}-{{{{arch}}}}/{{{{current_version}}}}");
let update = app .updater_builder() .endpoints(vec![update_url])? .build()? .check() .await?;🌐 Public key
在运行时设置公钥对于实现密钥轮换逻辑非常有用。它可以由插件构建器或更新构建器设置:
🌐 Setting the public key at runtime can be useful to implement a key rotation logic. It can be set by either the plugin builder or updater builder:
tauri_plugin_updater::Builder::new().pubkey("<your public key>").build()use tauri_plugin_updater::UpdaterExt;
let update = app .updater_builder() .pubkey("<your public key>") .build()? .check() .await?;🌐 Custom target
默认情况下,更新程序允许你使用 {{target}} 和 {{arch}} 变量来确定必须交付的更新资源。如果你需要有关更新的更多信息(例如,在分发通用 macOS 二进制选项或具有更多构建版本时),你可以设置自定义目标。
🌐 By default the updater lets you use the {{target}} and {{arch}} variables to determine which update asset must be delivered.
If you need more information on your updates (e.g. when distributing a Universal macOS binary option or having more build flavors)
you can set a custom target.
import { check } from '@tauri-apps/plugin-updater';
const update = await check({ target: 'macos-universal',});插件构建器或更新程序构建器都可以设置自定义目标:
🌐 Custom targets can be set by either the plugin builder or updater builder:
tauri_plugin_updater::Builder::new().target("macos-universal").build()use tauri_plugin_updater::UpdaterExt;let update = app .updater_builder() .target("macos-universal") .build()? .check() .await?;🌐 Allowing downgrades
默认情况下,Tauri 会检查更新版本是否高于当前应用版本,以验证是否应该进行更新。要允许降级,你必须使用更新器构建器的 version_comparator API:
🌐 By default Tauri checks if the update version is greater than the current app version to verify if it should update or not.
To allow downgrades, you must use the updater builder’s version_comparator API:
use tauri_plugin_updater::UpdaterExt;
let update = app .updater_builder() .version_comparator(|current, update| { // default comparison: `update.version > current` update.version != current }) .build()? .check() .await?;🌐 Windows before exit hook
由于 Windows 安装程序的限制,Tauri 会在 Windows 上安装更新之前自动退出你的应用。要在此之前执行操作,请使用 on_before_exit 函数:
🌐 Due to a limitation of Windows installers, Tauri will automatically quit your application before installing updates on Windows.
To perform an action before that happens, use the on_before_exit function:
use tauri_plugin_updater::UpdaterExt;
let update = app .updater_builder() .on_before_exit(|| { println!("app is about to exit on Windows!"); }) .build()? .check() .await?;🌐 Permissions
默认情况下,所有潜在危险的插件命令和作用域都会被阻止,无法访问。你必须在 capabilities 配置中修改权限以启用这些功能。
🌐 By default all potentially dangerous plugin commands and scopes are blocked and cannot be accessed. You must modify the permissions in your capabilities configuration to enable these.
有关更多信息,请参见功能概览,有关使用插件权限的分步指南,请参见分步指南。
🌐 See the Capabilities Overview for more information and the step by step guide to use plugin permissions.
{ "permissions": [ ..., "updater:default", ]}Default Permission
This permission set configures which kind of updater functions are exposed to the frontend.
Granted Permissions
The full workflow from checking for updates to installing them is enabled.
This default permission set includes the following:
allow-checkallow-downloadallow-installallow-download-and-install
Permission Table
| Identifier | Description |
|---|---|
|
|
Enables the check command without any pre-configured scope. |
|
|
Denies the check command without any pre-configured scope. |
|
|
Enables the download command without any pre-configured scope. |
|
|
Denies the download command without any pre-configured scope. |
|
|
Enables the download_and_install command without any pre-configured scope. |
|
|
Denies the download_and_install command without any pre-configured scope. |
|
|
Enables the install command without any pre-configured scope. |
|
|
Denies the install command without any pre-configured scope. |
Tauri 中文网 - 粤ICP备13048890号
Nodejs.cn 旗下网站