跨端框架Tauri的浅试
Tauri是什么
Tauri 是一个开源框架,用于构建轻量级、高性能的桌面应用程序。它是使用 Web 技术(如 HTML、CSS 和 JavaScript)来创建用户界面,同时利用 Rust 语言提供的api功能。Tauri 的目标是提供一种更高效、更安全的方式来开发跨平台的桌面应用程序。
<center><img src="https://s11.ax1x.com/2024/01/04/pixFEAs.png" width="500"></center>
Tauri 可以理解为多语言和通用工具包,具有很强的可组合性,允许工程师制作各种各样的应用程序。它用于使用 Rust 工具和 Web 视图中呈现的 HTML 的组合为台式计算机构建应用程序。使用 Tauri 构建的应用程序可以附带任意数量的可选 JS API 和 Rust API,以便 Web 视图可以通过消息传递来控制系统。开发人员可以使用自己的功能扩展默认 API,并轻松桥接 Webview 和基于 Rust 的后端。
Tauri 与框架无关。这意味着你可以将它与你选择的任何前端库一起使用——比如 Vue、React等或者纯Rust前端代码。你可以只使用 Tauri 提供的 JavaScript API 来构建你的整个应用程序。这样一来,您不仅可以轻松构建新应用,还可以将已构建的 Web 应用的代码库转换为本机桌面应用,而无需更改原始代码。
Tauri本身也可以用纯粹的Rust代码来写,比如使用Rust支持最好的WASM去写整个跨端项目也是可以。
Tauri VS Electron
提到前端跨端尤其是桌面端技术,就不得不提Electron技术。在桌面端方面,Electron是前辈,我们来对比一下,两者各自的优势。
<center><img src="https://media.licdn.com/dms/image/D4D12AQFGYts2hddorw/article-cover_image-shrink_720_1280/0/1679405533689?e=2147483647&v=beta&t=iLA4iZgzjEqJDwWefeOOmHqJP7ZssfesYz8XeG8nugc" width="500"></center>
Electron 的优势:
- 生态系统和社区:Electron 有一个更成熟和广泛的生态系统,拥有大量可用的库和工具。它的社区也更大,这意味着更多的资源、文档和支持。
- 成熟度和稳定性:Electron 已经被广泛使用多年,许多流行应用(如 VS Code、Slack)都是基于 Electron 构建的。因此,它在稳定性和功能性方面经过了更多的测试和验证。
- 开发便利性:由于 Electron 使用 Node.js,JavaScript 开发者可能会发现使用 Electron 更加方便,特别是对于那些已经熟悉 Node.js 生态系统的人。
- 功能丰富:Electron 由于其成熟度,通常提供更多的功能和集成选项。
Tauri 的优势:
- 性能和资源占用:Tauri 应用通常比 Electron 应用更轻量,占用更少的内存和磁盘空间。这是因为 Tauri 使用 Rust 作为api调用和系统交互,它比 Electron 中的 Node.js 更高效。
- 安全性:Tauri 提供更高的安全性,因为它限制了应用程序对系统资源的访问,而 Electron 通常给予更多的访问权限。
- 打包大小:Tauri 打包的应用程序体积通常比 Electron 小很多,这对于希望减小应用体积的开发者来说是一个重要优势。
- 能效:Tauri 应用程序通常比 Electron 更节能,尤其是在移动设备或低功耗设备上。
如何快速启动Tauri
以下是如何快速在一个React、Vue等前端项目里,加入Tauri框架,并且快速启动。
前提保证你的本地开发环境的Rust环境是正确的。首先在前端根目录中执行命令npm install --save-dev @tauri-apps/cli
,然后在文件package.json
中添加
"scripts": {
"tauri": "tauri"
}
然后在根目录中继续执行命令npm run tauri init
,这时候会在终端里询问交互几个问题(比如项目title和一些命令等),然后根目录中会生成出一个src-tauri
的目录,我们进入这个src-tauri
目录,需要在文件tauri.conf.json
更改一些属性,比如你需要之后build的话需要更改identifier
属性,其他重要的属性比如
"build": {
"beforeBuildCommand": "pnpm run build",
"beforeDevCommand": "pnpm run start",
"devPath": "http://localhost:4321",
"distDir": "../dist"
},
这其中,beforeBuildCommand
和beforeDevCommand
,是对应项目本身的build和dev命令,devPath
是对应前端启动的网络路径,distDir
对应前端项目build之后的包路径。
这以上的属性配置好之后,就可以在根目录中执行运行或者打包命令:
npm run tauri dev
npm run tauri build
Tauri框架的一些技巧
<center><img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTa5RjL5UtAhfsXyhT8R5IvhxPKVwzQjP0vyA&usqp=CAU" width="500"></center>
设置桌面端软件的菜单
创建菜单
在src-tauri
目录的main.rs
文件里,可以使用rust代码去增加桌面端软件的菜单功能(在Tauri 2.0中,menu的代码大部分功能都重构或更改了),这里就是添加一些简单的桌面端软件的。hide、show、quit等能力。
let app_menu = Submenu::new(
name,
Menu::with_items([
#[cfg(target_os = "macos")]
MenuItem::About(name.into(), AboutMetadata::default()).into(),
MenuItem::Hide.into(),
MenuItem::HideOthers.into(),
MenuItem::ShowAll.into(),
MenuItem::Quit.into(),
]),
);
// 主函数使用菜单
fn main() {
tauri::Builder::default()
.menu(menu)
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
监听快捷键按钮
这里代码是能在桌面端监听键盘的快捷键输入的,比如后退功能。
let view_menu = Submenu::new(
"View",
Menu::new()
.add_item(CustomMenuItem::new("go_back", "Go Back").accelerator("CmdOrCtrl+[")),
);
// 主函数使用监听事件
fn main() {
tauri::Builder::default()
.menu(menu::init())
.on_menu_event(menu::menu_handler)
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
使用指令
Tauri的指令功能,可以让rust代码可以跟JavaScript环境交互。这里用rust代码,申明了一个greet
方法,能够在主函数中注册之后,在Js的代码中自由调用。大家也可以把一些ui之外的,逻辑或者复杂计算的场景交给Rust,以提升整个软件的运行效率。
#[tauri::command]
fn greet(name: &str) -> String {
format!("Hello, {}!", name)
}
// 主函数注册指令
fn main() {
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![greet])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
import { invoke } from '@tauri-apps/api'
function App() {
invoke('greet', { name: 'World' })
.then((response) => console.log(response))
return ()
}
也可以使用withGlobalTauri
特性,可以在tauri.conf.json
文件里配置一下
"build": {
"beforeBuildCommand": "npm run build",
"beforeDevCommand": "npm run dev",
"devPath": "http://localhost:3000",
"distDir": "../build",
"withGlobalTauri": true
}
然后就可以在js环境里自由调用:
const { invoke } = window.__TAURI__.tauri
function App() {
invoke('greet', { name: 'World' })
.then((response) => console.log(response))
return ()
}
Tauri是如何工作的呢
在 Tauri 框架中,根据操作系统的不同(如 Windows 和 macOS),它会调用各自平台的原生能力来提供功能和性能。根据各自平台的一些webview能力来渲染的UI。
在 Electron 中,前端是与应用程序捆绑在一起的 Chromium 网页视图。这意味着,无论使用何种操作系统,始终可以确定应用使用的 Node.js 和 Chromium 版本。这带来了主要的好处,但也有一些缺点。
最大的好处是易于开发和测试,知道哪些功能可用,如果某些东西可以在 macOS 上运行,它很可能也可以在 Windows 和 Linux 上运行,并且渲染一致。但是,缺点是,由于捆绑了所有这些二进制文件,应用程序大小会大得多。
Tauri 采取了截然不同的方法。没有将 Chromium 与所需要的应用捆绑在一起,而是使用操作系统的默认 Web 视图。这意味着,比如在 macOS 上,应用将使用 WebKit(Safari 的引擎),在 Windows 上,它将使用 WebView2(基于 Chromium),在 Linux 上,它将使用 WebKitGTK(与 Safari 的相同)。最终这使得Tauri的应用结果是一个非常小的程序。
Tauri mobile
去年晚些时候即将到来的 2.0 稳定版本,Android 和 iOS 都将成为 Tauri 生态系统的一等公民。一些移动端的插件和系统的相互调用将登上tauri舞台。
<center><img src="https://studioterabyte.nl/ipx//images/blog/tauri-mobile-app-development/tauri_mobile_app.jpg" width="500"></center>
这里简单讲一下Tauri2.0的一些依赖和用法。
Tauri mobile 所需要的2.0依赖
Cargo.toml
文件所需要的2.0版本依赖:
[build-dependencies]
tauri-build = { version = "2.0.0-alpha.6", features = [] }
[dependencies]
serde_json = "1.0"
serde = { version = "1.0", features = ["derive"] }
tauri = { version = "^2.0.0-alpha", features = [] }
[features]
custom-protocol = [ "tauri/custom-protocol" ]
[lib]
crate-type = ["staticlib", "cdylib", "rlib"]
package.json
所需要添加的依赖:
"devDependencies": {
"@tauri-apps/cli": "^2.0.0-alpha"
}
Tauri mobile的一些命令
在项目根目录内可以使用命令,快速生成android或者ios的代码目录,如npm run tauri android init
或者npm run tauri ios init
,项目的src-tauri
目录就产生了gen
目录,其中就是移动端的自动生成的代码,我们除非签名或者其他配置才需要动他。然后想要运行或者打包安卓或ios的话,就使用命令:
-
npm run tauri android dev
ornpm run tauri ios dev
-
npm run tauri android build
ornpm run tauri ios build