JavaScript内核与高级编程之:`JavaScript` 的 `Tauri`:其在桌面应用中的 `Rust` 后端和 `Web` 前端。

各位观众老爷们,大家好!今天咱们来聊聊一个非常有意思的技术——JavaScript的Tauri。这玩意儿啊,能让你用熟悉的JavaScript撸前端,再用Rust写个硬核的后端,最后打包成一个桌面应用。是不是听起来就很带劲?

废话不多说,咱们直接上干货。

开场白:为什么是Tauri?

先说说为啥要用Tauri。现在桌面应用开发的选择很多,Electron很流行,但是Electron最大的问题是体积太大,而且性能也没那么好。Tauri就聪明多了,它用Rust做后端,Rust的性能那是杠杠的,编译出来的体积也小。前端呢,还是用你熟悉的HTML、CSS、JavaScript。相当于Electron的瘦身加强版。

第一部分:Tauri架构剖析

Tauri本质上是一个用Rust编写的框架,它利用系统WebView(比如Windows上的WebView2,macOS上的WebKit)来渲染前端。这就像搭积木,Rust后端提供动力和控制,WebView负责显示界面。

Tauri的核心组件:

  • Tauri Core (Rust): 这是Tauri的大脑,负责处理窗口管理、事件循环、系统调用等等。
  • WebView (系统自带): Tauri不自带浏览器内核,直接用系统自带的,大大减小了体积。
  • Front-end (HTML/CSS/JavaScript): 你熟悉的前端技术,负责构建用户界面。
  • Tauri API (Rust & JavaScript): Rust后端暴露出来的API,前端JavaScript可以通过它来调用系统功能。

第二部分:环境搭建与项目初始化

首先,确保你的电脑上装了Rust。没装的话,去Rust官网装一个,记得配置好环境变量。

然后,安装Tauri CLI:

cargo install tauri-cli

安装完之后,就可以创建Tauri项目了:

cargo create-tauri-app my-tauri-app

这个命令会问你几个问题,比如项目名称、UI框架等等。你可以根据自己的喜好选择。 如果你喜欢用React,那就选React。如果你喜欢Vue,那就选Vue。如果你想用Vanilla JS,那就选none。

创建成功后,进入项目目录:

cd my-tauri-app

项目结构大概是这样:

my-tauri-app/
├── .cargo/            # Rust相关的配置
├── .gitignore
├── Cargo.toml      # Rust项目的配置文件
├── src-tauri/        # Tauri后端代码
│   ├── Cargo.toml  # Tauri后端的配置文件
│   ├── src/        # Rust源代码
│   │   └── main.rs # 主函数
│   └── tauri.conf.json # Tauri配置文件
├── src/              # 前端代码
│   ├── index.html
│   ├── style.css
│   └── script.js
└── target/           # 编译输出目录

第三部分:前端代码编写

src/目录就是放前端代码的地方。你可以用任何你喜欢的UI框架,比如React、Vue、Svelte等等。

咱们先来个简单的例子,在src/index.html里写一个按钮,点击按钮的时候,在页面上显示一句话。

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>My Tauri App</title>
</head>
<body>
  <h1>Hello, Tauri!</h1>
  <button id="myButton">Click me!</button>
  <p id="message"></p>
  <script>
    const button = document.getElementById('myButton');
    const message = document.getElementById('message');

    button.addEventListener('click', () => {
      message.textContent = 'Tauri is awesome!';
    });
  </script>
</body>
</html>

这段代码很简单,就是一个按钮和一个段落。点击按钮的时候,段落的内容会变成 "Tauri is awesome!"。

第四部分:后端代码编写

src-tauri/src/main.rs是Tauri后端的入口文件。咱们可以在这里定义一些Rust函数,然后通过Tauri API暴露给前端调用。

比如,咱们写一个函数,接收前端传来的字符串,然后把字符串转换成大写,再返回给前端。

#![cfg_attr(
  all(not(debug_assertions), target_os = "windows"),
  windows_subsystem = "windows"
)]

use tauri::{command, State};
use std::sync::Mutex;

// 定义一个状态,用于在多个命令之间共享数据
struct MyState {
    count: Mutex<i32>,
}

#[command]
fn greet(name: &str) -> String {
  format!("Hello, {}! You've been greeted from Rust!", name)
}

#[command]
fn to_uppercase(input: String) -> String {
  input.to_uppercase()
}

#[command]
fn increment_count(state: State<'_, MyState>) -> i32 {
    let mut count = state.count.lock().unwrap();
    *count += 1;
    *count
}

fn main() {
    tauri::Builder::default()
        .manage(MyState { count: Mutex::new(0) }) // 初始化状态
        .invoke_handler(tauri::generate_handler![greet, to_uppercase, increment_count])
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

这段代码定义了两个函数:greetto_uppercasegreet函数接收一个字符串,然后返回一个问候语。to_uppercase函数接收一个字符串,然后把字符串转换成大写。

注意#[command]这个宏,它告诉Tauri这个函数可以被前端调用。

还有一点,Tauri支持状态管理,允许在多个命令之间共享数据。上面的代码中,我们定义了一个MyState结构体,包含一个count字段,用来记录计数。increment_count函数可以增加计数器的值。

第五部分:前后端交互

现在,咱们需要在前端调用Rust函数。Tauri提供了一个invoke函数,可以用来调用Rust函数。

修改src/script.js,添加以下代码:

const button = document.getElementById('myButton');
const message = document.getElementById('message');

button.addEventListener('click', async () => {
  // 调用Rust函数 greet
  const greeting = await window.__TAURI__.invoke('greet', { name: 'World' });
  message.textContent = greeting;

  // 调用 Rust 函数 to_uppercase
  const uppercaseText = await window.__TAURI__.invoke('to_uppercase', { input: 'hello tauri' });
  console.log(uppercaseText);

    // 调用 Rust 函数 increment_count
    const count = await window.__TAURI__.invoke('increment_count');
    console.log('Count:', count);
});

这段代码在点击按钮的时候,会调用Rust的greet函数,然后把返回的问候语显示在页面上。同时也会调用 to_uppercaseincrement_count 函数,并将结果打印到控制台。

注意window.__TAURI__.invoke这个函数,它是Tauri提供的,用来调用Rust函数。第一个参数是函数名,第二个参数是传递给函数的参数。

第六部分:构建与运行

一切准备就绪,就可以构建和运行Tauri应用了。

cargo tauri build

这个命令会编译Rust后端代码,然后把前端代码打包进去,生成一个可执行文件。

构建完成后,可以在target/release/目录下找到可执行文件。

直接运行这个可执行文件,就可以看到你的Tauri应用了。

或者,你也可以用以下命令来运行开发模式:

cargo tauri dev

这个命令会启动一个开发服务器,可以实时预览你的修改。

第七部分:Tauri API详解

Tauri提供了丰富的API,可以用来访问系统功能。

常用的API:

  • Window API: 窗口管理,比如创建窗口、关闭窗口、最大化窗口、最小化窗口等等。
  • Dialog API: 弹出对话框,比如打开文件对话框、保存文件对话框、消息对话框等等。
  • Notification API: 发送系统通知。
  • Shell API: 执行系统命令。
  • FS API: 文件系统操作,比如读取文件、写入文件、创建目录、删除文件等等。
  • HTTP API: 发送HTTP请求。
  • Global Shortcut API: 注册全局快捷键。
  • Clipboard API: 剪贴板操作。

举个例子,咱们用Dialog API打开一个文件选择对话框。

首先,在src-tauri/src/main.rs里添加以下代码:

use tauri::api::dialog::FileDialogBuilder;

#[command]
async fn open_file_dialog() -> Option<String> {
  let file_path = FileDialogBuilder::new().pick_file().await;
  file_path
}

这个函数会打开一个文件选择对话框,然后返回选择的文件路径。

然后,在src/script.js里添加以下代码:

const button = document.getElementById('myButton');
const message = document.getElementById('message');

button.addEventListener('click', async () => {
  const filePath = await window.__TAURI__.invoke('open_file_dialog');
  if (filePath) {
    message.textContent = `Selected file: ${filePath}`;
  } else {
    message.textContent = 'No file selected.';
  }
});

这段代码在点击按钮的时候,会调用Rust的open_file_dialog函数,然后把选择的文件路径显示在页面上。

第八部分:Tauri 安全性

Tauri非常注重安全性。Tauri应用默认情况下是沙盒化的,只能访问有限的系统资源。

Tauri使用权限系统来控制应用可以访问的系统功能。你需要在tauri.conf.json文件中声明应用需要的权限。

例如,如果你想让应用可以访问文件系统,需要在tauri.conf.json文件中添加以下配置:

{
  "tauri": {
    "security": {
      "csp": null
    },
    "allowlist": {
      "fs": {
        "all": true,
        "scope": ["$APP/*"]  // 允许访问应用程序目录下的所有文件
      }
    }
  }
}

这个配置允许应用访问应用程序目录下的所有文件。

第九部分:Tauri vs Electron

特性 Tauri Electron
后端 Rust Node.js
前端 HTML/CSS/JavaScript (系统 WebView) HTML/CSS/JavaScript (Chromium)
应用体积
性能 相对较低
安全性 高 (权限控制) 相对较低 (需自行处理)
资源占用
开发难度 稍高 (需要 Rust 知识) 较低 (JavaScript 开发者友好)
跨平台支持 支持 (主流平台) 支持 (主流平台)

总结:Tauri的优势与不足

优势:

  • 体积小: 使用系统 WebView,无需打包 Chromium,应用体积大大减小。
  • 性能高: Rust 后端提供卓越的性能。
  • 安全: 严格的权限控制,保障应用安全。
  • 资源占用低: Rust 和系统 WebView 降低了资源占用。

不足:

  • 学习曲线: 需要掌握 Rust 知识。
  • 生态: 相比 Electron,Tauri 的生态还不够完善。
  • 调试: Rust 代码调试相对复杂。

尾声:Tauri的未来展望

Tauri是一个很有潜力的技术,它结合了Rust的性能和JavaScript的灵活性,为桌面应用开发提供了一个新的选择。虽然目前Tauri的生态还不够完善,但是随着越来越多的开发者加入,相信Tauri的未来会更加美好。

好了,今天的分享就到这里。希望大家有所收获。如果有什么问题,欢迎提问。咱们下期再见!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注