视频版:
安装包体积减少91%!Tauri基础入门,下一代全平台开发框架,Tauri对比Electron有什么优势?
Tauri是一个全新跨平台应用开发框架,目前已经发布到了2.0版本。在Github上面的star数量已经飙升到了8万。开发者可以使用任意的JavaScript框架来设计开发UI,然后将同一套代码打包成全平台的桌面应用。2.0版本已经支持打包手机端的应用。
Tauri vs Electron
过去,Electron曾是桌面开发这一领域的王者。Electron使用Nodejs作为后台框架,Chronium内核作为前端引擎。不过Electron饱受诟病的问题是:安装包的体积过大,每个Electron应用都自带了一个完整的浏览器内核,导致大量硬盘空间被浪费,启动速度慢,系统资源占用高。
Tauri则另辟蹊径,采用了全新的技术架构。它使用Rust代替Nodejs作为后端语言,Rust具有内存安全、高性能、高并发等优点。Tauri使用了操作系统自带的Webview组件来渲染界面,从而不必在安装包里面集成Chronium内核。因此Tauri获得了更小的安装包体积、更低的资源消耗,还有更好的内存安全性。

Tauri的局限性
不过Tauri作为一个全新的框架,现阶段也存在一些缺点:
- Webview在每个操作系统上的底层实现不一样,这就会导致在不同系统上的页面渲染存在差异,会产生一些难以解决的兼容性问题。
- Tauri的社区活跃度不够,很多bug比较难以找解决方案。
- Rust陡峭的学习曲线让许多程序员望而却步,也增加了公司的招聘成本。
所以我的建议是:如果想构建小而美的桌面应用,或者对Rust感兴趣的朋友们,可以尝试使用Tauri。如果需要构建大型的桌面应用,暂时建议先观望一下。
开发环境搭建
接下来我们看一下如何在本地搭建一个Tauri的开发环境:
我们进入Tauri的官网tauri.app,进来以后点击get started,右上角可以切换成简体中文。我们从这里前置条件开始看。
我的电脑是Windows系统的,我们按照Windows的教程来看。我们找到系统依赖项,这里的最低版本是Windows 7。然后我们找到这里的Windows开发环境。
- 我们先下载Microsoft C++构件工具,Microsoft C++ 生成工具 - Visual Studio,也就是下载这个MSVC编译器。这个系统用来提供Rust跟操作系统底层的一些交互,也是我们开发Rust软件必须安装的一个工具。
- 这里点击下载,下载完成我们把它安装一下。右键以管理员身份运行,根据这个教程,我们只需要勾选这里的使用C++的桌面开发,然后点击安装。安装完成以后,我们按照提示重启一下电脑。
- WebView2在Windows 10以上的版本都默认自带了,所以就不用安装了。
- 接下来我们安装Rust。我们进入这个地址,Install Rust - Rust Programming Language 这里下载这个64位的Rust的安装包。接下来我们把Rust安装一下,这里双击安装。
- 接下来是Nodejs。现在大部分前端框架都需要Nodejs进行打包编译。我们进入Nodejs的首页nodejs.org,然后点击这里的下载。一路点击下一步就可以了。
创建第一个Tauri应用
接下来我们来创建Tauri应用。在Windows上面它推荐使用Powershell。那我们把Powershell的这个脚本复制一下,然后在桌面右键,在终端打开。这里确认开启了Powershell,然后我们把命令粘贴过来回车。
irm https://create.tauri.app/ps | iex
项目配置
- 首先我们提供一个项目的名称,这里我叫做shrimp-app。这里一个公司的名称,我直接回车。
- 接下来选择一个前端编程语言,这里我选择JavaScript/TypeScript。我们可以注意到,在2.0版本,Tauri不止可以选择JavaScript,也可以选择Rust或者.NET作为前端的编程语言。
- 接下来选择一个包管理工具,我使用npm。
- 接下来选择一个UI的模板,这里就可以选择你熟悉的前端框架,比如Vue或者React或者Angular。我选择第一个,使用HTML原生,不使用任何UI框架。
- 接下来选择一个你熟悉的编程语言,这里我选择JavaScript。

项目结构
这样桌面就多了一个文件夹,我们打开看一下。这个文件夹就是Tauri的一个工程,我们可以看到这里有两个src文件夹:
- 上面的src对应的是网页端的,也就是前端的源代码
- 下面的src-tauri对应的是后端,也就是Rust这边的源代码

启动项目
接下来我们进入项目目录:
- cd shrimp-app
- 然后npm install安装一下前端所需的依赖
- 这里node_modules文件夹就出现到了项目目录
- 接下来我把项目启动一下,就是npm run tauri dev

然后项目打开了一个全新的桌面应用,这个就是我们第一个Tauri的APP了。

我们可以在这里面随便填上一个名字,然后点击greet,下面弹出了一句输出。
Tauri的前后端交互
前端调用后端
这个demo页面本身就是一个前端调用后端的典型案例。我们进入JS代码看一下,这里面写了一个greet方法,每当用户点击这个greet按钮的时候,就会触发这个方法。这个方法调用了Tauri核心库的一个invoke方法,通过invoke方法前端可以直接调用后台的功能,然后这里传递了方法的名字,后面是具体方法的入参,也就是输入框里面的值。
const { invoke } = window.__TAURI__.core;
let greetInputEl;
let greetMsgEl;
async function greet() {
// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
greetMsgEl.textContent = await invoke("greet", { name: greetInputEl.value });
}
window.addEventListener("DOMContentLoaded", () => {
greetInputEl = document.querySelector("#greet-input");
greetMsgEl = document.querySelector("#greet-msg");
document.querySelector("#greet-form").addEventListener("submit", (e) => {
e.preventDefault();
greet();
});
});
后端响应
接下来我们进入后端的Rust代码。井号这一行是一个标注,用来标记这些代码可以被前端调用。然后这个greet方法必须与前端这里的greet是一模一样,大小写也必须一致。它的作用就是把刚才传入的输入框的名字拼接到字符串里面,然后再返回给前端。最后前端再构建一个标签栏,把Rust返回的内容输出出来。
// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
#[tauri::command]
fn greet(name: &str) -> String {
format!("Hello, {}! You've been greeted from Rust!", name)
}
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
.plugin(tauri_plugin_fs::init())
.plugin(tauri_plugin_shell::init())
.invoke_handler(tauri::generate_handler![greet])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
后端通知前端
我们接下来看如何从后端通过事件来通知前端。我们仿照这个greet重新写一个命令,这次我叫做greet2吧。我们在前面添加一个参数,这个APP代表的是前端的一个指针。我们不必在前端显式的传递这个参数,如果后台需要接收这个参数,Tauri会为我们自动把这个参数加上。然后我改一下这个函数的方法,这里新加一个叫做app.emit,指的是后台往前端推送事件。这里事件名字我叫做test_event,然后事件内容我是填一个hello。最后的unwrap简单处理一下rust的异常。然后我们需要在rust这边引入两个包,一个是刚才的APPHandle这个类,再一个是Emitter,就是这个Emit发送消息的方法。最后我们别忘了把这个函数在启动的时候注册一下。
// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
use tauri::{AppHandle, Emitter};
#[tauri::command]
fn greet(name: &str) -> String {
format!("Hello, {}! You've been greeted from Rust!", name)
}
#[tauri::command]
fn greet2(app: AppHandle,name: &str) {
app.emit("test_event","hello").unwrap();
}
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
.plugin(tauri_plugin_shell::init())
.invoke_handler(tauri::generate_handler![greet,greet2])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
好一切准备就绪,我们保存一下。可以看到保存成功以后,命令行这边就自动开始了编译。编译成功以后,APP也进行了重启。好接下来我们开始修改前端代码,修改前端代码不需要重启APP。
我在前端这里新引入了一个类,叫做listen,这个类的作用是监听后端推送的消息。
接下来我们写一个listen方法,这个方法监听了一个叫做test_event事件,也就是后端这里推送的这个事件的名字。接下来我们写一个回调函数,监听到事件以后,我们把事件里面的payload打印出来。好我们保存一下,最后一步,我们把调用按钮的事件改成greet2,也就是它调用后端的这个greet2方法,推送消息到前端,最后前端监听一下,打印出来。
const { invoke } = window.__TAURI__.core;
const { listen } = window.__TAURI__.event;
listen("test_event", (payload)=>{
console.log(payload);
});
let greetInputEl;
let greetMsgEl;
async function greet() {
// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
greetMsgEl.textContent = await invoke("greet", { name: greetInputEl.value });
}
window.addEventListener("DOMContentLoaded", () => {
greetInputEl = document.querySelector("#greet-input");
greetMsgEl = document.querySelector("#greet-msg");
document.querySelector("#greet-form").addEventListener("submit", (e) => {
e.preventDefault();
greet();
});
}); CopyRetryClaude can make mistakes. Please double-check responses.
好我们来测一下,这里我们还是打开APP,点击F12这里会弹出一个控制台窗口。我们可以像调试浏览器一样调试这个APP。我切换到控制台这里,然后我点击一下这个按钮,可以看到这里打印出来了事件,包括这里面的payload,还有事件的名字等等。

Tauri插件系统
除了我们可以自己定义前后台的API进行交互以外,Tauri还提供了一系列的官方API。在2.0版本里面叫做插件,这里我以最常见的文件系统的插件为例,演示一下我们如何调用官方的API来操作电脑上的文件系统。
首先使用包管理工具把这个插件安装一下,在控制台输入这串命令,
npm run tauri add fs
回车安装完成以后,
我们修改一下代码。这里还是刚才那个演示代码,我们首先先把官方插件引入到前台来。我需要两个功能,一个是写文件,还有一个是获取电脑上的目录。然后我把greet按钮的原来功能注释掉,这里我给它新加3行。我准备往文件里面写一行hello word,文件的名字叫做file.txt然后它的路径,我准备把它放到桌面上面。也就是说点击这个greet按钮的时候,就在桌面上写一个文件。
const { invoke } = window.__TAURI__.core;
const { writeFile, BaseDirectory } = window.__TAURI__.fs;
let greetInputEl;
let greetMsgEl;
async function greet() {
// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
//greetMsgEl.textContent = await invoke("greet", { name: greetInputEl.value });
let encoder = new TextEncoder();
let data = encoder.encode("Hello World");
await writeFile('file.txt', data, { baseDir: BaseDirectory.Desktop });
}
window.addEventListener("DOMContentLoaded", () => {
greetInputEl = document.querySelector("#greet-input");
greetMsgEl = document.querySelector("#greet-msg");
document.querySelector("#greet-form").addEventListener("submit", (e) => {
e.preventDefault();
greet();
});
});
Tauri有非常强大的权限控制系统,在默认情况下,所有的插件命令都被阻止,无法访问。所以,我们必须在这个capabilities里面新加一个关于权限的配置。好我们回到项目,capabilities/default.json这里我添加两个关于刚才那个写文件的权限。
添加这两行,指的是赋予他在桌面上写文件的权限。
fs:scope-desktop
fs:write-all
{
"$schema": "../gen/schemas/desktop-schema.json",
"identifier": "default",
"description": "Capability for the main window",
"windows": [
"main"
],
"permissions": [
"core:default",
"shell:allow-open",
"fs:default",
"fs:scope-desktop",
"fs:write-all"
]
}
一切准备就绪,我们保存一下,然后重启一下项目。好我们再点一下greet按钮,这里桌面多了一个文件。我们打开看一下,看到我这句话写进来了。
应用打包发布
最后我们来看一下如何打包,翻译成可发行的exe执行文件。这里我们执行这个命令
npm run tauri build
我们进入项目的src-tauri/target/release,这里面就可以找到打包出来的exe可执行文件。我们看一下它的大小,只有12兆,然后我再打一个zip包,只有3.51兆,这个安装包可比Electron小太多了。然后我们就可以把这个文件交付给小伙伴们,然后一起愉快的使用了。
结语
好本期视频是一个Tauri的基础介绍,如果想了解更多Tauri的使用方式的话,欢迎给我点个赞。本期视频就到这里,感谢大家,我们下期再见。
5207

被折叠的 条评论
为什么被折叠?



