跨平台桌面应用开发新选择 Tauri 2.0

Tauri 2.0

在 2024/10/02 官方正式发布了 Tauri 2.0 的稳定版本,这给我们构建跨平台桌面应用提供了新的选择。首先我们先了解一下 Tauri 是什么?

借用官方的话来说: Tauri 是用于为所有主流桌面(macOS、linux、windows)和移动(iOS、Android)平台构建微小二快速的二进制文件的框架。开发人员可以使用任何编译为 HTML、JavaScript 和 CSS 的前端框架来构建他们的应用,并且也可以在需要时使用 Rust、Swift 和 Kotlin 等语言来实现后端逻辑。总结一下 Tauri 是可以使用 Web 技术构建跨平台桌面应用,同时提供对系统本地资源访问能力的框架,没错,这介绍很容易想到另一个也是很好用的框架 Electron。Tauri 的优势在于轻量,性能,并且能提供更小的最终打包文件。

在 Tauri 开发过程中,因为 Tauri 是插件化开发,插件中会携带很多命令,例如关闭应用,读取文件,执行 shell 命令等。然而不进行**“权限配置”**是不能正常运行的,这就是复制官方文档中的代码无法达到相同效果的原因(在默认情况下,Tauri 不会自动请求权限,需要手动配置)。

如果你需要阅读更多关于 Tauri 2.0 的文档,可以查看官方 blog Tauri 2.0 Stable Release

如果是在后端写 Rust 来调用一些系统 API,不需要额外配置 Permission ,Permission 主要是约束前端行为。

Tauri Permission

对于前端内容来说,Permission 是一个重要概念,在 Tauri 开发中,经常会需要通过 JS API 来调用系统 API 或者其他 API。Tauri 的安全模型将 后端 Rust 代码和 WebView 前端代码分离,两端通过 IPC 层通信,确保边界不会被打破。(如果数据在边界之间没有控制的传递,容易被攻击者提升并滥用权限)。

tauri-4.png

如果你需要阅读更多关于 Tauri 安全的文档,可以点击这里

构建 Tauri 应用

在开始前请确定你已经安装好了必要的环境 : Node.js、Rust

  1. 创建应用
pnpm create tauri-app

这一步跟着提示选择即可,没有特别注意的地方。(下面例子中使用的是 React + TypeScirpt + vite)

使用命令 pnpm tauri dev 启动:

tauri-1.png

  1. 创建自定义窗口标题栏

Tauri 提供了三种方法修改 window 配置:

  • 通过 tauri.conf.json 文件修改
  • 通过 JS API 修改
  • 通过 Rust API 修改

这里主要介绍第二种,通过 JS API 修改窗口。

首先修改 tauri.conf.json 文件,隐藏默认的标题栏

{
  "app": {
    "windows": [
      {
        "title": "Tnode",
        "width": 800,
        "height": 600,
        "decorations": false
      }
    ],
    "security": {
      "csp": null
    }
  }
}

然后再 /src/ 中添加你的窗口,并通过 getCurrentWindow() 获取当前窗口实例,并添加对应的事件。

/src/App.tsx

import { getCurrentWindow } from "@tauri-apps/api/window";
···
return (
    <main className="container">
      <div data-tauri-drag-region className="titlebar">
        <div
          className="titlebar-button"
          onClick={() => {
            getCurrentWindow().minimize();
          }}
        >
          <img
            src="https://api.iconify.design/mdi:window-minimize.svg"
            alt="minimize"
          />
        </div>
        <div
          className="titlebar-button"
          onClick={() => {
            getCurrentWindow().maximize();
          }}
        >
          <img
            src="https://api.iconify.design/mdi:window-maximize.svg"
            alt="maximize"
          />
        </div>
        <div
          className="titlebar-button"
          onClick={() => {
            getCurrentWindow().close();
          }}
        >
          <img src="https://api.iconify.design/mdi:close.svg" alt="close" />
        </div>
      </div>
      ···
    </main>
)
···

这样就实现了自定义标题栏,效果如下:

tauri-2.png

看起来不错,但是当我们进行拖拽窗口时发现拖拽不动,点击按钮也没有反应。这是因为并没有添加对应的 Permissions,打开控制台可以看到对应的提示:

tauri-3.png

/tauri-app/src-tauri/capabilities/default.json 文件中添加 Permissions:

{
  "$schema": "../gen/schemas/desktop-schema.json",
  "identifier": "default",
  "description": "Capability for the main window",
  "windows": ["main"],
  "permissions": [
    "core:default",
    "shell:allow-open",
    "core:window:allow-close",
    "core:window:allow-minimize",
    "core:window:allow-maximize",
    "core:window:allow-start-dragging"
  ]
}

这样就可以正常拖拽窗口。

  1. 注册热键

最后试一下注册添加热键插件吧。

tauri 安装插件也非常简单:

pnpm tauri add global-shortcut
pnpm i

接下来的步骤和之前一样,首先在 web 添加对应的事件:

/src/App.tsx

import { register } from "@tauri-apps/plugin-global-shortcut";

function App() {
  const [fullScreen, setFullScreen] = useState(false);
    ···
  useEffect(() => {
    register("f1", (ev) => {
      if (ev.state === "Released") {
        console.log("F1 pressed");
        setFullScreen((prev) => !prev);
      }
    });
  }, []);

  useEffect(() => {
    const window = getCurrentWindow();
    if (fullScreen) window.setFullscreen(true);
    else window.setFullscreen(false);
  }, [fullScreen]);
    ···
}

当 tauri 安装插件后目录结构简化示例:

.
├── node_modules
├── src
├── src-tauri
│   └── capabilities
│       ├── default.json
│       └── desktop.json
├── tauri.conf.json

会发现在安装完 global-shortcut 插件后,capabilities 下多了一个 desktop.json 配置文件,在其中添加对应的 Permissions:

{
  "identifier": "desktop-capability",
  "platforms": [
    "macOS",
    "windows",
    "linux"
  ],
  "windows": [
    "main"
  ],
  "permissions": [
    "global-shortcut:default",
    "global-shortcut:allow-register"
  ]
}

最后需要在 tauri.conf.json 文件中声明以下配置:
capabilities 对应 desktop.json 中的 identifier

{
  "app": {
    "windows": [
      {
        "title": "Tnode",
        "width": 800,
        "height": 600,
        "decorations": false
      }
    ],
    "security": {
      "csp": null,
      "capabilities": ["default", "desktop-capability"]
    }
  }
}

到这 Tauri 的基本使用就结束了,接下来可以用 Tauri 构建你喜欢的桌面应用。