Tauri 打包发布完整指南 - 签名、更新、分发
前言
开发完应用后,最后也是最重要的一步就是打包和发布。这一步看似简单,实际上有很多需要注意的地方:如何优化打包体积?如何进行代码签名?如何实现自动更新?如何分发应用?
我第一次打包 Tauri 应用时,遇到了各种问题:Windows 上的 SmartScreen 警告、macOS 的 Gatekeeper 阻止、Linux 的依赖问题等。经过不断摸索,终于掌握了完整的打包发布流程。
今天,我就把这些经验分享给大家,让你少走弯路。
打包前的准备
1. 完善应用信息
编辑 src-tauri/tauri.conf.json:
json
{
"package": {
"productName": "Todo App", // 应用名称
"version": "1.0.0" // 应用版本(遵循语义化版本)
},
"tauri": {
"bundle": {
"active": true,
"targets": "all", // 打包所有格式
"identifier": "com.example.todoapp", // 唯一标识符(反向域名)
"icon": [ // 应用图标(多尺寸)
"icons/32x32.png",
"icons/128x128.png",
"icons/128x128@2x.png",
"icons/icon.icns", // macOS
"icons/icon.ico" // Windows
],
"copyright": "Copyright © 2025 Your Name",
"category": "Productivity", // 应用分类
"shortDescription": "A simple todo app",
"longDescription": "A beautiful and efficient todo application built with Tauri"
}
}
}2. 准备应用图标
图标要求:
- PNG 格式(Windows/Linux)
- ICNS 格式(macOS)
- ICO 格式(Windows)
推荐尺寸:
- 32x32
- 64x64
- 128x128
- 256x256
- 512x512
- 1024x1024
自动生成图标
bash
# 安装图标生成工具
npm install -g @tauri-apps/cli
# 从一个 PNG 文件生成所有尺寸的图标
npm run tauri icon path/to/your/icon.png3. 版本号管理
语义化版本规则:
主版本号.次版本号.修订号
1.0.0 - 初始版本
1.0.1 - 修复 bug
1.1.0 - 新增功能(向后兼容)
2.0.0 - 重大更新(可能不兼容旧版本)同步版本号:
json
// package.json
{
"version": "1.0.0"
}
// src-tauri/Cargo.toml
[package]
version = "1.0.0"
// src-tauri/tauri.conf.json
{
"package": {
"version": "1.0.0"
}
}Windows 平台打包
基本打包
bash
npm run tauri build输出文件位置:
src-tauri/target/release/bundle/
├── msi/ # MSI 安装包
│ └── Todo App_1.0.0_x64_en-US.msi
└── nsis/ # NSIS 安装包(可选)
└── Todo App_1.0.0_x64-setup.exeWindows 配置
json
{
"tauri": {
"bundle": {
"windows": {
"certificateThumbprint": null, // 证书指纹
"digestAlgorithm": "sha256", // 摘要算法
"timestampUrl": "", // 时间戳服务器
"wix": { // WiX 配置(MSI)
"language": "en-US",
"template": null,
"fragmentPaths": []
}
}
}
}
}代码签名
1. 获取代码签名证书
bash
# 选项1:从认证机构购买
# - DigiCert
# - GlobalSign
# - Sectigo
# 选项2:自签名证书(仅用于测试)
# 在 Windows PowerShell 中运行:
New-SelfSignedCertificate `
-Type CodeSigningCert `
-Subject "CN=Your Name, O=Your Organization, C=US" `
-KeyUsage DigitalSignature `
-FriendlyName "Code Signing Certificate" `
-CertStoreLocation "Cert:\CurrentUser\My" `
-TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.3")2. 配置签名
json
{
"tauri": {
"bundle": {
"windows": {
"certificateThumbprint": "YOUR_CERT_THUMBPRINT",
"timestampUrl": "http://timestamp.digicert.com"
}
}
}
}3. 手动签名
bash
# 使用 signtool.exe 手动签名
signtool sign /f certificate.pfx /p password /t http://timestamp.digicert.com /fd sha256 "Todo App.exe"解决 SmartScreen 警告
Windows SmartScreen 会对未签名或不知名的应用显示警告。
解决方案:
使用 EV 代码签名证书(最有效)
- 立即获得信誉
- 无需积累下载量
- 价格较高(约 $300-500/年)
积累信誉
- 使用普通代码签名证书
- 需要大量用户下载(几千次)
- 需要时间(几周到几个月)
提交给微软审核
- 提交到微软的 SmartScreen 服务
- 审核时间较长
macOS 平台打包
基本打包
bash
npm run tauri build输出文件位置:
src-tauri/target/release/bundle/
├── dmg/ # DMG 安装包
│ └── Todo App_1.0.0_x64.dmg
└── macos/ # .app 应用包
└── Todo App.appmacOS 配置
json
{
"tauri": {
"bundle": {
"macOS": {
"frameworks": [], // 额外框架
"minimumSystemVersion": "10.13", // 最低系统版本
"entitlements": null, // 权限配置文件
"exceptionDomain": "", // 网络异常域
"signingIdentity": null, // 签名身份
"providerShortName": null, // 提供商短名称
"hardenedRuntime": true // 加固运行时
}
}
}
}代码签名和公证
1. 获取开发者证书
bash
# 需要加入 Apple Developer Program($99/年)
# 证书类型:
# - Developer ID Application(用于分发)
# - Development(用于开发测试)
# 在钥匙串访问中查看证书
security find-identity -v -p codesigning2. 配置签名
json
{
"tauri": {
"bundle": {
"macOS": {
"signingIdentity": "Developer ID Application: Your Name (TEAM_ID)",
"hardenedRuntime": true,
"entitlements": "entitlements.plist"
}
}
}
}3. 创建 entitlements.plist
xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
<true/>
</dict>
</plist>4. 公证应用
bash
# 1. 上传应用到 Apple
xcrun altool --notarize-app \
--primary-bundle-id "com.example.todoapp" \
--username "your@email.com" \
--password "@keychain:AC_PASSWORD" \
--file "Todo App.dmg"
# 2. 检查公证状态
xcrun altool --notarization-info REQUEST_UUID \
--username "your@email.com" \
--password "@keychain:AC_PASSWORD"
# 3. 公证成功后,装订票据
xcrun stapler staple "Todo App.dmg"5. 自动化公证
创建 notarize.sh:
bash
#!/bin/bash
APP_NAME="Todo App"
BUNDLE_ID="com.example.todoapp"
APPLE_ID="your@email.com"
TEAM_ID="TEAM_ID"
# 签名
codesign --deep --force --verify --verbose --sign "Developer ID Application: Your Name ($TEAM_ID)" \
--options runtime "$APP_NAME.app"
# 创建 DMG
hdiutil create -volname "$APP_NAME" -srcfolder "$APP_NAME.app" -ov -format UDZO "$APP_NAME.dmg"
# 签名 DMG
codesign --force --sign "Developer ID Application: Your Name ($TEAM_ID)" "$APP_NAME.dmg"
# 公证
xcrun altool --notarize-app \
--primary-bundle-id "$BUNDLE_ID" \
--username "$APPLE_ID" \
--password "@keychain:AC_PASSWORD" \
--file "$APP_NAME.dmg"Linux 平台打包
基本打包
bash
npm run tauri build输出文件位置:
src-tauri/target/release/bundle/
├── deb/ # Debian/Ubuntu
│ └── todo-app_1.0.0_amd64.deb
├── rpm/ # Fedora/RHEL
│ └── todo-app-1.0.0-1.x86_64.rpm
└── appimage/ # AppImage(通用)
└── todo-app_1.0.0_amd64.AppImageLinux 配置
json
{
"tauri": {
"bundle": {
"deb": {
"depends": [], // 依赖包
"files": {}, // 额外文件
"desktopTemplate": null // 桌面文件模板
},
"appimage": {
"bundleMediaFramework": false, // 是否打包媒体框架
"files": {} // 额外文件
}
}
}
}创建桌面文件
创建 src-tauri/assets/todo-app.desktop:
ini
[Desktop Entry]
Version=1.0
Type=Application
Name=Todo App
Comment=A simple todo application
Exec=todo-app
Icon=todo-app
Categories=Utility;
Terminal=false依赖处理
bash
# 查看应用依赖
ldd target/release/todo-app
# 常见依赖:
# - libwebkit2gtk-4.0
# - libgtk-3
# - libayatana-appindicator3
# 在 tauri.conf.json 中配置
{
"tauri": {
"bundle": {
"deb": {
"depends": [
"libwebkit2gtk-4.0-37",
"libgtk-3-0",
"libayatana-appindicator3-1"
]
}
}
}
}自动更新
1. 配置更新器
json
{
"tauri": {
"updater": {
"active": true,
"endpoints": [
"https://releases.example.com/{{target}}/{{current_version}}"
],
"dialog": true, // 显示更新对话框
"pubkey": "YOUR_PUBLIC_KEY" // 公钥(用于验证签名)
}
}
}2. 生成密钥对
bash
# 安装 Tauri CLI
npm install -g @tauri-apps/cli
# 生成密钥对
npm run tauri signer generate
# 输出:
# Public Key: dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6...
# Private Key: saved to ~/.tauri/myapp.key将公钥配置到 tauri.conf.json:
json
{
"tauri": {
"updater": {
"pubkey": "YOUR_PUBLIC_KEY_HERE"
}
}
}3. 签名更新包
bash
# 构建应用
npm run tauri build
# 签名更新文件
npm run tauri signer sign target/release/bundle/msi/Todo\ App_1.0.0_x64_en-US.msi这会生成 .sig 文件:
Todo App_1.0.0_x64_en-US.msi.sig4. 创建更新服务器
创建 update-manifest.json:
json
{
"version": "1.0.1",
"notes": "Bug fixes and improvements",
"pub_date": "2025-01-21T12:00:00Z",
"platforms": {
"windows-x86_64": {
"signature": "SIGNATURE_FROM_SIG_FILE",
"url": "https://releases.example.com/windows/Todo_App_1.0.1_x64_en-US.msi"
},
"darwin-x86_64": {
"signature": "SIGNATURE_FROM_SIG_FILE",
"url": "https://releases.example.com/macos/Todo_App_1.0.1_x64.dmg"
},
"darwin-aarch64": {
"signature": "SIGNATURE_FROM_SIG_FILE",
"url": "https://releases.example.com/macos/Todo_App_1.0.1_aarch64.dmg"
},
"linux-x86_64": {
"signature": "SIGNATURE_FROM_SIG_FILE",
"url": "https://releases.example.com/linux/todo-app_1.0.1_amd64.AppImage"
}
}
}5. 前端检查更新
typescript
import { checkUpdate, installUpdate } from '@tauri-apps/api/updater';
import { relaunch } from '@tauri-apps/api/process';
async function checkForUpdates() {
try {
const { shouldUpdate, manifest } = await checkUpdate();
if (shouldUpdate) {
console.log(`New version available: ${manifest?.version}`);
console.log(`Release notes: ${manifest?.body}`);
// 下载并安装更新
await installUpdate();
// 重启应用
await relaunch();
} else {
console.log('App is up to date');
}
} catch (error) {
console.error('Failed to check for updates:', error);
}
}
// 应用启动时检查更新
useEffect(() => {
checkForUpdates();
}, []);6. 自动更新最佳实践
typescript
import { useState, useEffect } from 'react';
import { checkUpdate, installUpdate } from '@tauri-apps/api/updater';
import { relaunch } from '@tauri-apps/api/process';
function UpdateChecker() {
const [updateAvailable, setUpdateAvailable] = useState(false);
const [updateInfo, setUpdateInfo] = useState<any>(null);
const [downloading, setDownloading] = useState(false);
useEffect(() => {
checkForUpdates();
}, []);
const checkForUpdates = async () => {
try {
const { shouldUpdate, manifest } = await checkUpdate();
if (shouldUpdate) {
setUpdateAvailable(true);
setUpdateInfo(manifest);
}
} catch (error) {
console.error('Update check failed:', error);
}
};
const handleUpdate = async () => {
setDownloading(true);
try {
await installUpdate();
await relaunch();
} catch (error) {
console.error('Update failed:', error);
setDownloading(false);
}
};
if (!updateAvailable) return null;
return (
<div className="update-banner">
<div className="update-content">
<h3>New version available: {updateInfo?.version}</h3>
<p>{updateInfo?.body}</p>
</div>
<button
onClick={handleUpdate}
disabled={downloading}
>
{downloading ? 'Downloading...' : 'Update Now'}
</button>
</div>
);
}打包优化
1. 减小体积
toml
# Cargo.toml
[profile.release]
panic = "abort" # 禁用堆栈展开
codegen-units = 1 # 减少并行代码生成单元
lto = true # 启用链接时优化
opt-level = "z" # 优化体积
strip = true # 去除符号信息2. 前端优化
bash
# 使用生产构建
npm run build
# 启用压缩
# vite.config.ts
export default defineConfig({
build: {
minify: 'terser',
terserOptions: {
compress: {
drop_console: true, # 移除 console
drop_debugger: true # 移除 debugger
}
},
rollupOptions: {
output: {
manualChunks: {
vendor: ['react', 'react-dom']
}
}
}
}
});3. 资源优化
bash
# 压缩图片
npm install -g imagemin-cli
imagemin src/assets/*.png --out-dir=dist/assets --plugin=pngquant
# 优化 SVG
npm install -g svgo
svgo src/assets/*.svgCI/CD 自动化
GitHub Actions 配置
创建 .github/workflows/release.yml:
yaml
name: Release
on:
push:
tags:
- 'v*'
jobs:
release:
strategy:
matrix:
platform: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.platform }}
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Node
uses: actions/setup-node@v3
with:
node-version: 18
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
- name: Install dependencies (Ubuntu)
if: matrix.platform == 'ubuntu-latest'
run: |
sudo apt-get update
sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev \
libayatana-appindicator3-dev librsvg2-dev
- name: Install Node dependencies
run: npm install
- name: Build
run: npm run tauri build
- name: Upload artifacts
uses: actions/upload-artifact@v3
with:
name: ${{ matrix.platform }}
path: |
src-tauri/target/release/bundle/**/*.deb
src-tauri/target/release/bundle/**/*.dmg
src-tauri/target/release/bundle/**/*.msi
src-tauri/target/release/bundle/**/*.AppImage
- name: Create Release
uses: softprops/action-gh-release@v1
if: startsWith(github.ref, 'refs/tags/')
with:
files: |
src-tauri/target/release/bundle/**/*.deb
src-tauri/target/release/bundle/**/*.dmg
src-tauri/target/release/bundle/**/*.msi
src-tauri/target/release/bundle/**/*.AppImage
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}分发渠道
1. 官网下载
html
<!-- 下载页面 -->
<div class="download-section">
<h2>Download Todo App</h2>
<div class="download-options">
<a href="/downloads/windows/latest" class="download-btn">
<i class="icon-windows"></i>
Windows
</a>
<a href="/downloads/macos/latest" class="download-btn">
<i class="icon-apple"></i>
macOS
</a>
<a href="/downloads/linux/latest" class="download-btn">
<i class="icon-linux"></i>
Linux
</a>
</div>
</div>2. GitHub Releases
bash
# 创建标签
git tag -a v1.0.0 -m "Version 1.0.0"
git push origin v1.0.0
# GitHub Actions 会自动构建并发布3. 应用商店
Microsoft Store
- 注册开发者账号($19 一次性费用)
- 准备应用信息和截图
- 使用 MSIX 打包(Tauri 支持)
- 提交审核
Mac App Store
- 加入 Apple Developer Program($99/年)
- 配置 App Store 签名和沙盒
- 准备应用信息和截图
- 使用 Transporter 上传
- 提交审核
Snap Store(Linux)
bash
# 创建 snapcraft.yaml
name: todo-app
version: '1.0.0'
summary: A simple todo application
description: |
A beautiful and efficient todo application
confinement: strict
grade: stable
apps:
todo-app:
command: todo-app
plugs: [network, home]
parts:
todo-app:
plugin: dump
source: .
stage-packages:
- libwebkit2gtk-4.0-37
- libgtk-3-0
# 构建和发布
snapcraft
snapcraft upload todo-app_1.0.0_amd64.snap4. Homebrew(macOS)
创建 formula:
ruby
class TodoApp < Formula
desc "A simple todo application"
homepage "https://example.com/todo-app"
url "https://github.com/username/todo-app/releases/download/v1.0.0/Todo-App-1.0.0.dmg"
sha256 "..."
version "1.0.0"
def install
prefix.install "Todo App.app"
end
end发布检查清单
打包前
- [ ] 更新版本号(package.json, Cargo.toml, tauri.conf.json)
- [ ] 更新 CHANGELOG
- [ ] 测试所有功能
- [ ] 检查控制台是否有错误
- [ ] 优化资源文件
- [ ] 更新文档
打包后
- [ ] 在各平台测试安装包
- [ ] 验证应用功能
- [ ] 检查应用体积
- [ ] 测试更新功能
- [ ] 验证代码签名
发布后
- [ ] 上传到分发渠道
- [ ] 更新官网
- [ ] 发布 Release Notes
- [ ] 社交媒体宣传
- [ ] 监控错误报告
常见问题
Windows 相关
问题:SmartScreen 警告
- 使用 EV 代码签名证书
- 或积累应用信誉
问题:打包失败
- 检查 Visual Studio Build Tools 安装
- 确认 Rust 工具链完整
macOS 相关
问题:Gatekeeper 阻止
- 进行代码签名和公证
- 用户可以右键点击"打开"绕过
问题:公证失败
- 检查 entitlements.plist 配置
- 确认开发者证书有效
Linux 相关
问题:缺少依赖
- 在打包配置中声明依赖
- 或使用 AppImage(包含所有依赖)
问题:权限问题
- 检查文件权限
- 使用 chmod +x 赋予执行权限
总结
🎉 恭喜!你已经掌握了 Tauri 应用的完整打包发布流程!
✅ 核心知识
打包配置
- 应用信息配置
- 图标准备
- 版本管理
平台特定
- Windows: MSI/NSIS, 代码签名
- macOS: DMG/App, 签名和公证
- Linux: DEB/RPM/AppImage
自动更新
- 更新器配置
- 密钥生成和签名
- 更新服务器
优化和自动化
- 体积优化
- CI/CD 配置
- 多渠道分发
🎯 最佳实践
- 始终进行代码签名
- 提供自动更新功能
- 多平台测试
- 完善的文档和支持
💡 下一步
- 收集用户反馈
- 持续优化性能
- 定期发布更新
- 扩展功能
至此,Tauri 系列教程就全部完成了!从入门到实战,从开发到发布,相信你已经具备了开发 Tauri 应用的完整能力。
系列文章回顾:
- Tauri 是什么?为什么它是桌面应用开发的未来
- Tauri 开发环境搭建 - Windows/macOS/Linux 完整指南
- Tauri 快速开始 - 15 分钟创建第一个应用
- Tauri 核心概念深度解析 - 架构、安全与配置
- Tauri 窗口管理与高级通信技巧
- Tauri 实战项目 - 从零开始构建 Todo 应用
- Tauri 打包发布完整指南 - 签名、更新、分发
感谢阅读!有任何问题欢迎留言讨论!
参考资料: