Tauri 踩坑实录之 App 无法启动

现象

首先说明,作者的开发平台为 Win11,所以程序在 Windows 上运行是完全没有问题的,其次作者有 Linux 和 Macos 的环境,在 dev 模式下也都能够正常运行。

但在发布 mission-backup 首个正式版本 v1.0.0 后陆续收到反馈,问题如下:

  • macOS 平台程序无法启动
  • Linux 平台 .deb 运行正常,.AppImage 会出现权限错误

看起来 Linux 这边问题好解决,那就让我们先看 macOS 吧!

MacOS 排查

是不是前端?

我们的第一个怀疑对象是前端,这是为什么呢?

如果你对 Tauri 有一定的了解,那你一定知道 Tauri 是通过调用系统的 Webview 来进行前端的渲染和实现的,而不同系统间这部分的实现也有各自的不同:对于 Windows 来说就是原生的 Webview2,对于 Linux 来说是 WebkitGTK,而对于 macOS 来说则是 Webkit

在 Tauri 中负责这部分的底层库是 WRY。由于 Webview 对于 Tauri 来说是必须的,因此我们常常也会在程序开始前检测系统是否有可用的 Webview,类似下面这段代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
use wry::webview::webview_version;
use native_dialog::{ MessageDialog, MessageType };

pub fn check_webview2_available(scope: AppHandle) {
let system_webview2_version = webview_version().unwrap();
println!("System webview2 version: {}", system_webview2_version);

if system_webview2_version == "" {
println!("System missing webview2 bundle");

let result = MessageDialog::new()
.set_type(MessageType::Error)
.set_title("Error")
.set_text("Missing Webview Bundle")
.show_confirm()
.unwrap();

if result {
let _jump_to_download_page = tauri::scope::ShellScope::open(
&scope.shell_scope(),
"https://developer.microsoft.com/zh-cn/microsoft-edge/webview2/#download-section",
None,
);
std::process::exit(0);
}
}
}

当我们在 Windows 平台运行含上述代码的程序时,我们将看到如下结果

Webview2 version

而当我们在 macOS 上执行的时候,结果是这样的

Webkit version

看到这版本差距了吗,只能说很难不让人先怀疑到前端身上是不是🤔。

当然,也请放心,既然 Tauri 目前已经是在正式版本,说明最后问题其实并不在这里。我们可以通过对官方 template 的实验来证明,简单的 build 以后我们发现至少 template 确实是在各个平台都能正常运行的。

而在我们将 template 的前端代码替换为我们的前端代码后,我们也可以发现程序能够正常运行。这就充分证明了程序问题并不在前端问题上,那看来只能是后端出问题了。

是你吗后端?

在进行后端的排查的时候,由于程序编写的时候就是各功能模块分开来编写的,彼此之间并没有什么特别紧密的联系,因此我们通过逐一屏蔽不同模块就可以确定问题是否由该模块导致,然后再进一步检查模块内部的功能影响。

很快我们就找到了嫌疑人:splashscreen 加载页。

Missing splashscreen.html

提示相当明显,我们的 splashscreen.html 文件实际上是缺失的,可我们调试的时候明明是一切正常的,而且也是完全按照官方指南 Tauri: Splashscreen 做的,怎么会有这样的问题呢?莫不是个 bug?

遇 bug 麻利提 issue:[bug] Macos missing splashscreen after build ,官方页回的很及时,原因呢,其实很简单:

还记得指南里说我们的 splashscreen.html 文件要放在哪里吗?是 distDir,即项目根目录下,与 vite.config.ts 是一层的,而对于 vue 来说,这一层的文件并不会打包到我们最终的 bundle 中去,这就导致了程序运行时无法找到相应资源文件,从而无法正常启动。

解决方法当然也很简单,复制一份 splashscreen.html 到项目的 public 目录下即可,该目录下的文件将会自动打包至最终的 bundle 中去。

问题找到了,问题解决了,现在程序一定能正常启动了吧!

很遗憾,并不是。情况反而变得有点 更加奇怪。

简单来说,我们现在可以安装,不能双击运行,但在直接进入包内容以命令行形式运行后,它又是正常的。

Start with shell

由于作者也不太熟悉 macOS,暂时找不到更多方向了,先回头解决 Linux 的权限问题吧!

Linux 排故

Linux 这个问题看起来,相当简单,不就是权限不够吗,上 sudo!

Failed with sudo

发现不行,那直接给个 777 权限!

Failed with 777

还是不行,看起来有点玄学,玄学问题玄学解决,要不试试打包的时候就是 sudo?

很可惜还是不行,这就起了个怪了,难道又是个 bug?或者以为是个 bug 其实是自己菜没看出来?

我们还是先猜 bug 吧,想要验证也很简单,问题出在文件创建上,那我们在模板上稍微添点

1
2
3
4
5
6
7
8
9
use std::fs::File;
use std::io::prelude::*;

fn main() {
let mut file = File::create("config.ini").unwrap();
file.write_all(b"Hello, world!").unwrap();

tauri::Builder........
}

这代码足够简单了吧,足够卑微了吧,清清白白的模板,简简单单用官方库创建个文件,写点内容,不过分吧!

Failed to create file

抱歉,还是一样的权限错误。到了这里,其实熟悉 Linux 开发的小伙伴应该已经发现是什么问题了,可惜的是我这时候还是完全不懂并怀疑一切的状态。

于是我提了个 issue: [bug] Appimage seems have permission problem ,然后发现完全是自己的问题…

原来对于 Appimage, 它是不认相对路径的!

虽然它是个直接执行的文件,类似 .exe,但是我们给出的路径必须是绝对的,而且甚至说现在你可能考虑使用 std::process::current_exe 这也是不行的。

那知道原因当然好改了,所有路径用绝对路径锁死,程序最终顺利跑起来了。

Finally working

意外之喜的是,现在程序在 macOS 下也能正常跑了,看来原因和 Linux 的是一致的,大概是因为都是类 Unix 的原因吧。

结语

其实看下来大部分坑踩的都是因为自己菜的原因,Tauri 本身还是挺靠谱的。

希望我收获的这些经验能对你有所帮助,下个坑见!


Tauri 踩坑实录之 App 无法启动
http://example.com/2022/10/18/Tauri-踩坑实录之-App-无法启动/
作者
Stein
发布于
2022年10月18日
许可协议