Tauri踩坑分享

5,596 阅读3分钟

引言

之前分享了 Tauri 初探,最近的一段时间使用 Tauri 在项目上实现了一些功能。遇到了一些坑,做个分享。

http 跨域问题

Tauri 实现的一般是一个 pc 的客户端程序,一般会有对服务端取数据的需求。可能这是一个局域网程序,所以也懒得部署 https 服务了。这时候 Tauri dev 下调试运行时正常的, 但是当你做完功能想编译成一个 exe 运行时,会发现网络请求失败了。

大致错误描述

The page at '<URL>' was loaded over HTTPS,

原因么就是 windows 上 Tauri 是基于 webview2 实现的,在安全性上有一些限制。目前该问题也没有得到完美的解决。不过经过研究,发现 Tauri 还是提供了一个方法,就是使用他提供的 http.fetch 接口来调用请求。然后发现控制台是无法查看到网络请求的。得出结论他是通过 Tauri 里面的 rust 去帮我们调用请求从而绕过了 webview2 前端框架。

所以 Tauri 里面的网络如果非 https 的话,就不能使用 axios 这个网络库了。而应该使用他提供的 http.fetch。

简单封装下

export enum RemoteUrl {
  remoteA,
  remoteB,
}

export const FetchGet = async (
  remote: RemoteUrl,
  path: string
): Promise<any> => {
  const url = await (remote === RemoteUrl.remoteA ? remoteA() : remoteB());
  return http.fetch(`${url}${path}`, { method: 'GET' });
};

export const FetchPost = async (
  remote: RemoteUrl,
  path: string,
  body: any | null = null
): Promise<any> => {
  const url = await (remote === RemoteUrl.remoteA ? remoteA() : remoteB());
  return http.fetch(`${url}${path}`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: body,
  });
};

这里是存在多个服务端的情况

使用的代码

export const getSomething = (id: string) => {
  return FetchGet(RemoteUrl.remoteA, `/getPath/${id}`);
};

export const postSomething = (data: {
  name: string;
  label: string[];
  a: any[];
}): Promise<any> => {
  return FetchPost(RemoteUrl.remoteB, '/postPath', {
    type: 'Json',
    payload: data,
  });
};

ps:2023/6/13 fetch只能解决http的问题,但有时候我们还会用到websocket,这时候如果是局域网环境的app,可以试用localhost插件。 目前tauri官网提供了插件库,里面有localhost插件,支持http、ws, 这也是一个绕过安全墙的方式。

善用 event

Tauri 封装了个挺好用的 event。可以让你轻松的在 rust 代码和 H5 之间轻松的消息通信。

大致撸了个案例

fn main() {
    let menu = Menu::new();
    return tauri::Builder::default()
        .menu(menu)
        .setup(|app| {
            // 持有apphandle的复制对象。然后可以对他为所欲为
            let app_cp = app.handle();
            //  在rust里面监听从h5发出来的消息
            app.listen_global("new_window", |event| {
                println!("{:?}", event);
            });
            // 建个线程,间隔5s朝外部广播消息
            tauri::async_runtime::spawn(async move {
                loop {
                    tokio::time::sleep(Duration::from_millis(5000)).await;
                    // 朝所有监听了haha事件的对象发消息
                    _ = app_cp.emit_all(
                        "haha",
                        TestData {
                            aa: "sss".to_string(),
                            bb: "ddd".to_string(),
                        },
                    );
                    _ = app_cp.emit_all("hehe", "sdsds");
                    // 单独对main window发送hehe事件
                    app_cp.emit_to("main", "hehe", "123123");
                }
            });
            Ok(())
        })
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

H5 实现


import { listen } from '@tauri-apps/api/event';

listen('haha', (event) => {
    console.log('listen event', event);
});

结尾

暂时也没啥更多的分享,后续遇到大坑在补。

吐槽下Tauri的文档着实太少了。关于自定义安装配置的更是少之又少,还待探索。

国内貌似用Tauri的人很少,不知道有没有朋友有加群互帮互助的想法,在下摸鱼的方向比较多。最近在扩展rust技术栈,搞搞React,SwfitUI。

要加群的可以私信我