安装包体积减少91%!Tauri基础入门,下一代全平台开发框架,Tauri对比Electron有什么优势?

视频版:

安装包体积减少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作为一个全新的框架,现阶段也存在一些缺点:

  1. Webview在每个操作系统上的底层实现不一样,这就会导致在不同系统上的页面渲染存在差异,会产生一些难以解决的兼容性问题。
  2. Tauri的社区活跃度不够,很多bug比较难以找解决方案。
  3. Rust陡峭的学习曲线让许多程序员望而却步,也增加了公司的招聘成本。

所以我的建议是:如果想构建小而美的桌面应用,或者对Rust感兴趣的朋友们,可以尝试使用Tauri。如果需要构建大型的桌面应用,暂时建议先观望一下。

开发环境搭建

接下来我们看一下如何在本地搭建一个Tauri的开发环境:

我们进入Tauri的官网tauri.app,进来以后点击get started,右上角可以切换成简体中文。我们从这里前置条件开始看。

我的电脑是Windows系统的,我们按照Windows的教程来看。我们找到系统依赖项,这里的最低版本是Windows 7。然后我们找到这里的Windows开发环境。

  1. 我们先下载Microsoft C++构件工具,Microsoft C++ 生成工具 - Visual Studio,也就是下载这个MSVC编译器。这个系统用来提供Rust跟操作系统底层的一些交互,也是我们开发Rust软件必须安装的一个工具。
  2. 这里点击下载,下载完成我们把它安装一下。右键以管理员身份运行,根据这个教程,我们只需要勾选这里的使用C++的桌面开发,然后点击安装。安装完成以后,我们按照提示重启一下电脑。
  3. WebView2在Windows 10以上的版本都默认自带了,所以就不用安装了。
  4. 接下来我们安装Rust。我们进入这个地址,Install Rust - Rust Programming Language 这里下载这个64位的Rust的安装包。接下来我们把Rust安装一下,这里双击安装。
  5. 接下来是Nodejs。现在大部分前端框架都需要Nodejs进行打包编译。我们进入Nodejs的首页nodejs.org,然后点击这里的下载。一路点击下一步就可以了。

创建第一个Tauri应用

接下来我们来创建Tauri应用。在Windows上面它推荐使用Powershell。那我们把Powershell的这个脚本复制一下,然后在桌面右键,在终端打开。这里确认开启了Powershell,然后我们把命令粘贴过来回车。

irm https://create.tauri.app/ps | iex

项目配置

  1. 首先我们提供一个项目的名称,这里我叫做shrimp-app。这里一个公司的名称,我直接回车。
  2. 接下来选择一个前端编程语言,这里我选择JavaScript/TypeScript。我们可以注意到,在2.0版本,Tauri不止可以选择JavaScript,也可以选择Rust或者.NET作为前端的编程语言。
  3. 接下来选择一个包管理工具,我使用npm。
  4. 接下来选择一个UI的模板,这里就可以选择你熟悉的前端框架,比如Vue或者React或者Angular。我选择第一个,使用HTML原生,不使用任何UI框架。
  5. 接下来选择一个你熟悉的编程语言,这里我选择JavaScript。

项目结构

这样桌面就多了一个文件夹,我们打开看一下。这个文件夹就是Tauri的一个工程,我们可以看到这里有两个src文件夹:

  • 上面的src对应的是网页端的,也就是前端的源代码
  • 下面的src-tauri对应的是后端,也就是Rust这边的源代码

启动项目

接下来我们进入项目目录:

  1. cd shrimp-app
  2. 然后npm install安装一下前端所需的依赖
  3. 这里node_modules文件夹就出现到了项目目录
  4. 接下来我把项目启动一下,就是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的使用方式的话,欢迎给我点个赞。本期视频就到这里,感谢大家,我们下期再见。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值