Tauri 2 Windows 桌面应用脚手架
> slug:tauri2-windows-scaffold | 显示名称:Tauri 2 Windows 桌面应用脚手架
用途
在 Windows 上从零搭建并交付一个可运行的空白 Tauri 2 + Rust 桌面应用骨架,
覆盖工具链准备、项目脚手架、依赖与链接故障修复、小体积 exe 构建、
前端资源内嵌,以及 GUI 渲染效果的截图验证。
本技能不包含任何业务逻辑,只负责把「空壳程序 + 构建链路」跑通;
具体功能在骨架之上按 references/app-skeleton.md 的 command 范式自行扩展。
硬性规范(必须遵守)
规范 1:只交付体积小巧的 exe
- 唯一交付形态是 release 构建的 exe,目标体积 约 5–15MB
- 禁止把 debug 版 exe 当作交付物。debug 版即使能独立运行也约 250MB
(含调试符号),只允许作为开发期临时自检,不得交付 - 禁止为了「快速出 exe」而牺牲体积,包括不通过降低优化等级、
不 strip、改用 debug 构建等方式换取时间 - 体积不达标时先排查原因(是否误用 debug、strip 是否生效、依赖是否过大),
再考虑进一步压缩手段
规范 2:UI 必须使用 Semantic UI + raised + 双主题
- CSS 框架固定为 Semantic UI(
semantic-ui-css) - 所有内容区块统一使用
ui raised segment卡片样式作为主题基调 - 必须提供 深色 / 浅色两套主题,且 默认深色
- 主题切换要持久化(localStorage),刷新后保持用户选择
实现细节、CSS 变量清单与切换代码见 references/ui-semantic-theme.md,
骨架模板 assets/template/ 已内置完整实现。
工作流
1. 探测环境,决定工具链
先确认 rustc / cargo 是否存在、是否有 MSVC(C:\Program Files\Microsoft Visual Studio)
或 MinGW(gcc --version)、以及 WebView2 运行时。
- 有 MSVC → 直接用
x86_64-pc-windows-msvc,跳过第 2 步 - 两者都没有 → 走 GNU 路线(无需安装 VS、无需管理员),执行第 2 步
2. 准备 GNU 工具链(按需)
安装 rustup 的 stable-x86_64-pc-windows-gnu 与 winlibs MinGW-w64(UCRT / posix-seh)。
详细命令与校验见 references/windows-gnu-toolchain.md,
也可用 scripts/setup_gnu_toolchain.sh 一键完成下载、解压与冒烟测试。
每个新开的 shell 都必须先注入 PATH,否则 cargo 找不到链接器。
3. 复制空白骨架
assets/template/ 是一套可直接编译运行的最小项目,已内置
Semantic UI + raised 区块 + 深浅双主题(默认深色)+ 一个示例 command:
cp -r <skill>/assets/template/. <目标目录>/
cd <目标目录> && npm install
复制后按 assets/template/README.md 的清单替换应用名(共 5 处:
package.json 的 name、Cargo.toml 的 name 与 [lib].name、
tauri.conf.json 的 productName / identifier / 窗口 title)。
4. 必须的 Cargo.toml 配置(含瘦身)
[lib]
name = "app_lib"
# 不要生成 cdylib:MinGW 下导出符号数会超出 GNU ld 限制
crate-type = ["staticlib", "rlib"]
[build-dependencies]
tauri-build = { version = "2", features = [] }
# 修复 tauri-utils -> schemars(preserve_order) -> indexmap 1.x 缺 std 特性
indexmap = { version = "1.9", features = ["std"] }
[dependencies]
tauri = { version = "2", features = [] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
indexmap = { version = "1.9", features = ["std"] }
[profile.release]
# 体积优先:opt-level "s",极致场景可改 "z"
opt-level = "s"
# 绝不要 codegen-units = 1 + lto = true:MinGW 下 fat LTO 单线程全量优化,
# 实测 58 分钟仍未完成链接(体积收益也有限)
codegen-units = 16
lto = false
panic = "abort" # 去掉 unwind 表,明显减小体积
strip = true # 剥离调试符号
incremental = false
5. 构建小体积 exe
npm run build # 前端 dist
cd src-tauri && cargo build --release # 交付用的 exe
ls -la src-tauri/target/release/*.exe # 确认体积在 5–15MB 量级
时间预期:依赖首次编译 20–40 分钟(4 核)。若超过 45 分钟仍停留在单个 rustc 进程上,
优先怀疑 lto / codegen-units 配置,而不是继续等待。
体积不达标时的排查顺序:
- 确认用的是
--release(debug 版约 250MB) - 确认
strip = true与panic = "abort"已生效 - 检查前端
dist/是否塞入过大资源(字体、图片、整包图标库) - 检查 Rust 依赖是否被误开启大量特性(
cargo tree -e features) - 可选:UPX 压缩(注意部分杀毒软件会误报)
开发期需要脱离 dev server 自检时,可临时构建
cargo build --features tauri/custom-protocol(原理见坑位表),
但该 debug 产物体积巨大,严禁作为交付物。
6. 开发模式(热重载)
npm run tauri dev 在部分环境会因 CLI 无法用 cmd 派生 npm 而失败(os error 231)。
改为手动双开:先起 npm run dev,再 cargo build 并运行 debug exe。
7. 验证 GUI 渲染效果
用 scripts/capture_window.py <输出.png> <窗口标题关键字> 抓取窗口内容。
它基于 PrintWindow(PW_RENDERFULLCONTENT),在被遮挡或 RDP 会话下也能拿到 WebView2 内容
(普通 BitBlt 全屏截取在 RDP 下会得到全黑图)。详见 references/tauri-build-pitfalls.md。
验证要点:确认深色主题为默认、区块呈现 raised 卡片效果、
切换浅色后配色正确、数据/交互正常。
8. 在骨架上扩展功能
- 后端:在
src-tauri/src/lib.rs增加#[tauri::command]函数并注册到
generate_handler!;需要共享数据时用tauri::State<Mutex<T>> - 前端:用
invoke('命令名')调用,类型定义与 Rust 结构体字段保持一致 - 新增 UI 区块时继续沿用
ui raised segment,不要另起炉灶换框架 - 新增插件后记得在
capabilities/default.json中声明对应权限
范式与目录约定见 references/app-skeleton.md。
坑位速查表
| 症状 | 根因 | 修复 |
|---|---|---|
| exe 体积 200MB+ | 交付了 debug 构建 | 改用 cargo build --release,并确认 strip = true |
| exe 体积偏大(几十 MB) | panic 未 abort / 未 strip / 前端资源过大 |
开 panic = "abort"、strip = true,精简 dist/ 资源 |
schemars 报 IndexMap 泛型/特性错误 |
tauri-utils 启用 schemars 的 preserve_order,其依赖的 indexmap 1.x 未开 std |
在 [dependencies] 与 [build-dependencies] 同时声明 indexmap = { version = "1.9", features = ["std"] },靠特性合并生效 |
ld.exe: export ordinal too large |
crate-type 含 cdylib,导出表超出 GNU ld 限制 |
改为 ["staticlib", "rlib"] |
| release 编译 1 小时仍未完成 | lto = true + codegen-units = 1 → 单线程 fat LTO |
改 lto = false、codegen-units = 16 |
| vite 报缺少 esbuild / rollup 原生二进制 | npm 跳过 optional 平台依赖 | npm i @esbuild/win32-x64@<版本>、npm i @rollup/rollup-win32-x64-msvc@<版本>(版本与主包对齐) |
npm run tauri dev 报 os error 231 |
tauri CLI 无法用 cmd 派生 npm | 手动分开启动 vite 与 exe |
| debug exe 显示「localhost 拒绝连接」 | debug 版走 devUrl,没有 dev server |
加 --features tauri/custom-protocol,或起 vite |
| 截图全黑 | RDP 会话下 BitBlt 取不到画面 |
用 PrintWindow(..., 2) 抓目标窗口 |
| GUI 进程在命令结束后立即消失 | 后台子进程被回收 | 需要长驻时改用前台后台任务,并在同一条命令内完成启动与检查 |
| 合成鼠标滚轮 / 按键无法滚动 webview | 合成输入限制 | 临时在页面注入 scrollTo 脚本借 HMR 截图,事后还原 |
完整原理与排查细节见 references/tauri-build-pitfalls.md。
资源索引
assets/template/— 可直接编译运行的空白项目骨架(含 Semantic UI + 双主题实现)references/app-skeleton.md— 骨架结构说明、command 范式、前后端交互与扩展约定references/ui-semantic-theme.md— Semantic UI 接入、raised 区块、深色/浅色双主题实现references/windows-gnu-toolchain.md— GNU 工具链安装、PATH 注入、冒烟测试references/tauri-build-pitfalls.md— 依赖冲突、链接失败、构建提速、体积与 GUI 验证scripts/setup_gnu_toolchain.sh— 一键下载安装 rustup + MinGW-w64 并验证scripts/make_tauri_icons.py— 纯 Python 生成 Tauri 所需全部图标(含 icon.ico)scripts/capture_window.py— 抓取指定窗口内容为 PNG,用于验证 GUI