更新
Tauri 为 NSIS(Windows)、MSI(Windows)、AppImage(Linux)和 App bundle(macOS)分发格式提供内置更新程序。
一旦你的 Tauri 项目准备就绪,你就可以配置 Tauri 的更新程序,为你的用户启用自动更新。
签名更新
Tauri 的更新程序具有内置签名机制,可确保安全安装更新。
要签名更新,您需要两样东西:
- 公钥,稍后将添加到
tauri.conf.json
文件中,用于在安装前验证更新工件。 - 私钥,用于签署您的更新工件,绝对不能与任何人共享。此外,如果丢失了此密钥,您将无法向当前用户群发布新的更新。将它存放在一个安全的地方,以便随时可以访问,这一点至关重要。
要在 Linux 和 macOS 上生成密钥,可以使用 Tauri CLI:
- npm
- Yarn
- pnpm
- Cargo
npm run tauri signer generate -- -w ~/.tauri/myapp.key
yarn tauri signer generate -w ~/.tauri/myapp.key
pnpm tauri signer generate -w ~/.tauri/myapp.key
cargo tauri signer generate -w ~/.tauri/myapp.key
如果使用的是 Windows 系统,则应使用 $HOME/.tauri/myapp.key
或其他路径:
- npm
- Yarn
- pnpm
- Cargo
npm run tauri signer generate -- -w $HOME/.tauri/myapp.key
yarn tauri signer generate -w $HOME/.tauri/myapp.key
pnpm tauri signer generate -w $HOME/.tauri/myapp.key
cargo tauri signer generate -w $HOME/.tauri/myapp.key
Tauri配置
现在,你需要配置Tauri的更新程序。为此,请在 Tauri 配置中添加以下内容:
{
"tauri": {
"updater": {
"active": true,
"endpoints": [
"https://releases.myapp.com/{{target}}/{{arch}}/{{current_version}}"
],
"dialog": true,
"pubkey": "YOUR_UPDATER_SIGNATURE_PUBKEY_HERE"
}
}
}
所需的密钥包括 "active"
、"endpoints"
和 "pubkey"
,以启用更新程序。"dialog"
为可选项,如果未设置,默认为 true
。
"active"
必须是布尔值。默认设置为 false。
"endpoints"
必须是以字符串形式表示的更新器端点 URL 数组。在生产模式下会强制使用 TLS。
每个更新器 URL 可以包含以下变量,以便在服务器端确定更新是否可用:
{{current_version}}
: 请求更新的应用程序版本。{{target}}
: 操作系统名称(linux
、windows
或darwin
之一)。{{arch}}
: 机器的架构(x86_64
、i686
、aarch64
或armv7
之一)。
"pubkey"
必须是用上述 Tauri CLI 生成的有效公钥。
"dialog"
必须是布尔值。默认设置为 true。如果启用,更新器事件将被禁用,因为内置对话框会处理所有事件。如果需要自定义事件,则必须关闭内置对话框。
Windows 上的 installMode
在 Windows 系统中,还有一个额外的可选配置 "installMode"
,用于更改更新的安装方式。
{
"tauri": {
"updater": {
"windows": {
"installMode": "passive"
}
}
}
}
"passive"
: 这时会出现一个带有进度条的小窗口。更新将在不需要用户交互的情况下完成安装。一般推荐使用默认模式。"basicUi"
: 将显示一个基本用户界面,需要用户交互才能完成安装。"quiet"
: 用户不会收到任何进度反馈。在此模式下,安装程序无法自行请求管理员权限,因此它只适用于用户范围内的安装或应用程序本身已使用管理员权限运行的情况。一般不推荐使用。
更新构件
一旦更新程序正确配置并启用,Tauri 的打包程序将自动生成并签署更新构件。
在构建应用程序之前,您需要为私钥和密码设置环境变量:
TAURI_PRIVATE_KEY
: 私钥的路径或内容TAURI_KEY_PASSWORD
: 您的私钥密码(可选)
如果想在当前控制台会话中设置这些变量,可以在控制台中执行这些命令,稍后再用来构建应用程序:
- Bash
- PowerShell
export TAURI_PRIVATE_KEY="content of the generated key"
export TAURI_KEY_PASSWORD="password"
$env:TAURI_PRIVATE_KEY="content of the generated key"
$env:TAURI_KEY_PASSWORD="password"
之后,你可以像往常一样运行 tauri build
,Tauri 就会生成更新程序包及其签名。
-
Linux: 在 Linux 上,Tauri 将从
target/release/bundle/appimage/
文件夹中的 AppImage 创建.tar.gz
压缩包:myapp.AppImage
- 标准应用程序包。myapp.AppImage.tar.gz
- 更新程序包。myapp.AppImage.tar.gz.sig
- 更新包的签名。
-
macOS: 在 macOS 上,Tauri 将从
target/release/bundle/macos/
文件夹中的应用程序程序包创建.tar.gz
压缩包:myapp.app
- 标准应用程序包。myapp.app.tar.gz
- 更新程序包。myapp.app.tar.gz.sig
- 更新包的签名。
-
Windows: 在 Windows 系统中,Tauri 将从
target/release/bundle/msi/
和target/release/bundle/nsis
文件夹中的 MSI 和 NSIS 安装程序创建.zip
压缩包:myapp-setup.exe
- 标准应用程序包。myapp-setup.nsis.zip
- 更新程序包。myapp-setup.nsis.zip.sig
- 更新包的签名。myapp.msi
- 标准应用程序包。myapp.msi.zip
- 更新程序包。myapp.msi.zip.sig
- 更新包的签名。
只要私钥安全,签名就可以安全上传和共享。
服务器支持
Tauri 的更新程序支持两种公布更新数据的方式:
- 静态 JSON 文件(用于 S3 或 GitHub gists 等服务)
- 动态更新服务器
静态 JSON 文件更容易使用,而动态更新服务器则能让你对更新机制进行更精细的控制。
静态 JSON 文件
通过这种方法,Tauri 将始终请求相同的 JSON 文件,并通过比较响应的版本字段和请求应用程序的当前版本来确定应用程序是否需要更新。Tauri 将期望得到这种格式的响应:
{
"version": "v1.0.0",
"notes": "Test version",
"pub_date": "2020-06-22T19:25:57Z",
"platforms": {
"darwin-x86_64": {
"signature": "Content of app.tar.gz.sig",
"url": "https://github.com/username/reponame/releases/download/v1.0.0/app-x86_64.app.tar.gz"
},
"darwin-aarch64": {
"signature": "Content of app.tar.gz.sig",
"url": "https://github.com/username/reponame/releases/download/v1.0.0/app-aarch64.app.tar.gz"
},
"linux-x86_64": {
"signature": "Content of app.AppImage.tar.gz.sig",
"url": "https://github.com/username/reponame/releases/download/v1.0.0/app-amd64.AppImage.tar.gz"
},
"windows-x86_64": {
"signature": "Content of app-setup.nsis.sig or app.msi.sig, depending on the chosen format",
"url": "https://github.com/username/reponame/releases/download/v1.0.0/app-x64-setup.nsis.zip"
}
}
}
必填键为 "version"
、"platforms.[target].url"
和 "platforms.[target].signature"
;其他键为可选键。
"version"
必须是一个有效的 semver,带或不带前导v
,即1.0.0
和v1.0.0
都有效。"platforms"
: 每个平台密钥都是OS-ARCH
格式,其中OS
是linux
、darwin
或windows
之一,ARCH
是x86_64
、aarch64
、i686
或armv7
之一。"url"
必须是更新包的有效网址。"signature"
必须是生成的.sig
文件的内容。每次运行tauri build
时,签名都可能发生变化,因此请务必随时更新。"notes"
: 您可以在此添加有关更新的说明,如发布说明。Tauri 的默认对话框会在询问是否允许更新时向用户显示此内容。"pub_date"
如果存在,必须按照 RFC 3339 格式化。
请注意,在检查版本字段之前,Tauri 将验证整个文件,因此请确保所有现有平台配置都是有效和完整的。
动态更新服务器
使用这种方法,Tauri 将遵循更新服务器的指示。要禁用内部版本检查,可以覆盖 Tauri 的版本比较,始终安装服务器发送的版本。如果需要快速回滚应用程序版本,这将非常有用。
服务器可以使用上述endpoint
url 中定义的变量来确定是否需要更新。如果您需要更多数据,可以根据自己的喜好在 Rust 中加入额外的请求头。
如果没有可用的更新,服务器应响应 204 No Content
状态代码。
如果需要更新,服务器将以 200 OK
状态代码和以下格式的 JSON 响应:
{
"version": "0.2.0",
"pub_date": "2020-09-18T12:29:53+01:00",
"url": "https://mycompany.example.com/myapp/releases/myrelease.tar.gz",
"signature": "Content of the relevant .sig file",
"notes": "These are some release notes"
}
必填键为 "url"、"版本 "和 "签名",其他键为可选键。
"version"
必须是一个有效的 semver,带或不带前导v
,即1.0.0
和v1.0.0
都有效。"url"
必须是更新包的有效网址。"signature"
必须是生成的.sig
文件的内容。每次运行tauri build
时,签名都可能发生变化,因此请务必随时更新。"notes"
: 您可以在此添加有关更新的说明,如发布说明。Tauri 的默认对话框会在询问是否允许更新时向用户显示此内容。"pub_date"
如果存在,必须按照 RFC 3339 格式化。
检查更新
内置对话框
默认情况下,更新程序会在内部使用 Tauri 的 dialog.ask API 显示一个对话框。该对话框只会在应用程序刚刚启动或手动触发 "tauri://update"
事件时检查是否有新的更新。
对话框发布说明由服务器提供的更新说明表示。如果用户接受,将下载并安装更新。随后,系统会提示用户重新启动应用程序。
自定义对话框
您需要在 Tauri 配置中禁用内置对话框,以启用 JavaScript API 和更新器事件!
Rust
有关 Rust API,请参阅 docs.rs 上的 updater 模块文档。
JavaScript
有关完整的 API 文档,请参阅此处。使用 JavaScript API 的示例如下:
import {
checkUpdate,
installUpdate,
onUpdaterEvent,
} from '@tauri-apps/api/updater'
import { relaunch } from '@tauri-apps/api/process'
const unlisten = await onUpdaterEvent(({ error, status }) => {
// 这将记录所有更新器事件,包括状态更新和错误。
console.log('Updater event', error, status)
})
try {
const { shouldUpdate, manifest } = await checkUpdate()
if (shouldUpdate) {
// 您可以显示一个对话框,询问用户是否要在此处安装更新。
console.log(
`Installing update ${manifest?.version}, ${manifest?.date}, ${manifest?.body}`
)
// 安装更新。这也将在 Windows 上重新启动应用程序!
await installUpdate()
// 在 macOS 和 Linux 上,您需要手动重启应用程序。
// 您可以使用此步骤显示另一个确认对话框。
await relaunch()
}
} catch (error) {
console.error(error)
}
// 如果处理程序超出范围,例如组件被卸载,则需要调用 unisten。
unlisten()