1. 核心心智模型:Tauri 就像"静态站点宿主"
Tauri 的前端加载方式很像静态站点托管:你最终必须提供一份能被 WebView 直接加载的静态资源目录(HTML/CSS/JS/WASM)。
因此 Trunk 在这套体系中的定位非常明确:
- 开发时:
trunk serve启动 dev server,Tauri 窗口加载devUrl - 构建时:
trunk build产出静态目录(通常是dist/),Tauri 把frontendDist打包进应用
这也解释了为什么 Checklist 的第一条一定是 SSG(静态路线)。
2. Checklist:三条必做项,对应三个常见"坑"
2.1 使用 SSG(静态资源输出)
Tauri 不官方支持依赖服务端渲染/服务端运行时的方案。所以你的 WASM 前端最终要落成静态资源(Trunk build 的产物)供 WebView 加载。
2.2 配置 serve.ws_protocol = "ws"(移动端热重载关键)
移动端开发(尤其真机)时,热重载 websocket 连接更容易因为网络/协议环境不一致出现连不上或断线。显式指定 ws_protocol = "ws" 能让热重载更稳定。
2.3 开启 withGlobalTauri(让 WASM 能拿到 Tauri API)
开启后,Tauri 会把 API 注入到 window.__TAURI__,你就可以在 WASM(通过 wasm-bindgen / JS interop)中更方便地访问它。
不打开这个开关,你经常会遇到"WASM 里找不到 TAURI / 无法导入 Tauri API"的问题。
3. 示例配置 1:src-tauri/tauri.conf.json
把下面配置写入或合并到 src-tauri/tauri.conf.json:
json
{
"build": {
"beforeDevCommand": "trunk serve",
"beforeBuildCommand": "trunk build",
"devUrl": "http://localhost:8080",
"frontendDist": "../dist"
},
"app": {
"withGlobalTauri": true
}
}
字段解释(非常重要):
beforeDevCommand: "trunk serve"
你执行cargo tauri dev时,Tauri 会先帮你启动 Trunk dev server。devUrl: "http://localhost:8080"
Tauri 开发模式的 WebView 加载地址。注意它必须与你的 Trunk serve 端口一致。beforeBuildCommand: "trunk build"
你执行cargo tauri build时,先构建 WASM 静态资源。frontendDist: "../dist"
Trunk build 输出目录。因为tauri.conf.json在src-tauri/下,所以通常要回到上一级找dist。withGlobalTauri: true
注入window.__TAURI__,为 WASM 调用 Tauri API 做准备。
4. 示例配置 2:Trunk.toml
在项目根目录(与 index.html 同级)放置或修改 Trunk.toml:
ini
[watch]
ignore = ["./src-tauri"]
[serve]
ws_protocol = "ws"
两个点分别解决什么:
watch.ignore = ["./src-tauri"]
避免 Trunk 去 watch Rust/Tauri 后端目录,减少无意义的 rebuild,也能规避某些平台上文件句柄过多的问题。serve.ws_protocol = "ws"
移动端热重载的稳定性关键项。
如果你还需要显式指定端口(让它和 devUrl 完全一致),也可以在 [serve] 下增加 port = 8080(按你项目实际端口来)。
5. 运行方式:两条命令就够了
开发(弹窗运行):
cargo tauri dev
构建(输出安装包/可执行文件):
cargo tauri build
因为你已经在 tauri.conf.json 里配置了 beforeDevCommand/beforeBuildCommand,所以一般不需要手动先执行 trunk serve 或 trunk build。
6. WASM 侧如何访问 Tauri API(思路与建议)
开启 withGlobalTauri 后,window.__TAURI__ 会存在。你有两种常见做法:
做法 A:WASM 只管业务,Tauri 调用封装在一层 JS wrapper(推荐)
- JS 写一个很薄的 wrapper,比如
invokeXxx(),里面调用window.__TAURI__ - WASM 通过
wasm-bindgen调 wrapper 函数
优势:边界清晰、类型可控、后期权限治理更好做
做法 B:WASM 直接从 window 上取 __TAURI__
- 通过
web-sys/js-sys访问全局对象
优势:少一层封装;但后期项目大了会比较散
如果你要做工程化落地,我建议从 A 开始:把 Tauri 能力收敛成少数几个"应用服务接口",后续做 capability 管控也更清爽。
7. 常见问题速查
- Tauri 窗口打开但白屏
先检查devUrl是否与你的 Trunk serve 端口一致(例如 8080),再看 trunk 是否真的启动成功。 - 热重载在移动端/真机不工作
优先确认Trunk.toml中ws_protocol = "ws"是否设置。 - WASM 里找不到
window.__TAURI__
检查tauri.conf.json是否启用了"withGlobalTauri": true,并确认你是在 Tauri WebView 里运行(不是单纯浏览器打开页面)。