一、前言
通过前面一个章节的内容,大家应该能大概理解tauri框架的工作流程了。
但仅此就想要上手开发还是远远不够的,所以本文我将会把对tauri的使用理解尽可能通俗易懂的写出来,让大家能够快速上手实际应用的开发。
二、vue开发
按照官方的说法是,你使用任何前端框架都是可以的,但由于我目前比较熟悉vue,国内前端的大趋势也是vue,所以这里以vue3作为前端开发tauri项目为例。
不会vue的,可以参照本站系列教程文章:vue初识
首先还是运行上一章提到的命令:
npm create tauri-app@latest
效果如下:
运行该命令后,除了第一个是让你填写项目名外,其它都是让你选填一些配置项,也就是上图绿色字体的文本。
我选择的就是一般用法:
- 使用ts/js作为前端开发
- 包管理为npm
- ui模板为vue
- 风格选择ts
总结来说就是使用TypeScript作为前端开发语法,vue作为框架、npm作为包管理工具。
然后你只需要挨着去执行上图第二个红框中的前两条命令,就能完成以vue作为前端的tauri框架搭建。
第一个cd test
是进入新建的项目文件夹,这里叫test
。
然后第二条npm install
是前端安装所需要的包。
至于npm run tauri android init
是进行安卓开发初始化的,这里先不用管,后文会对其进行介绍。
对于桌面端开发来说,重点是npm run tauri dev
这条命令,它会将应用程序启动起来,并时刻监视当前项目中的文件变化,一旦发生变化,就会自动更新程序。
单说这一点就比electron
方便的多,electron
官方没有提供任何前端框架绑定、以及代码文件监视功能并实时重构程序,你需要使用第三方的开源项目才行、麻烦而繁琐,而这里的tauri直接一行命令就搞定了。
等开发完毕后,同样是使用类似的命令npm run tauri build
完成最终的程序构建。
然后我们就可以来到其自动构建的项目文件夹中:
这里的src
和src-tauri
想来大家应该已经有所熟悉了,它就是前文提到的作用:
src
:存放前端代码的文件夹,比如js、ts、vue等前端文件,这和正常的前端项目是一样的src-tauri
:存放后端代码的文件夹,也就是rust代码。
至于.vscode
文件夹就不用多说了,它就是vscode的配置文件。
然后是public
文件夹,用来存放一些前端资源的,比如图片,这个熟悉前端的都应该很清楚。
至于之后的其它文件,也都是前端vue中的内容了,这里就不再赘述了,不清楚的可以先去学习vue框架:vue初识。
所以总的来说,tauri其实仅仅只是在一个前端的框架中创建了一个src-tauri
的文件夹用来写rust代码而已。
如果你能熟练使用一套前端框架,那么也能很快上手开发,仅仅只是在需要扩展前端的本地功能时才需要写rust代码来进行扩展,然后使用前面提到的invoke
函数来进行调用。
同时要注意的是,依靠这种由前端框架搭建的项目,你可以直接在代码中引入该函数使用:
上面就是自动生成的示例代码中的例子,就通过引入的这个invoke
函数去调用后端rust代码中注册的一个叫做greet
的函数:
注意这里src
目录下有lib.rs
与main.rs
这两个源码文件,而main.rs
中的main
入口函数又调用了lib.rs
这里的run
函数。
之所以这样做,是为了兼容安卓开发,在tauri1.0版本时代不支持安卓开发时就只有一个main.rs
文件,如果你是从tauri1.0迁移过来的,那么直接将这里的lib.rs
当作之前的main.rs
使用即可。
类似invoke
这样的函数当然不止一个,事实上官方提供了相当多的函数可以供我们调用,很多时候并不需要我们自己去写rust代码,可以直接调用官方提供好的接口。
你可以从官方文档不同的模块中找到对应的函数:
比如invoke这个函数就在api/core这个模块下,所以前面我们代码中也是这样引入的。
三、进程模型
通过前面一小节的内容,现在你就已经可以开发桌面应用了:
- 将vue作为前端创建tauri项目
- 在
src
文件中像正常的vue项目那样写代码即可,并且还可以运行命令npm run tauri dev
实时看到效果。 - 如果有需要扩展的本地功能,就在
src-tauri
文件夹中实现相应的函数、注册,然后在前端用invoke
函数进行调用。 - 最后开发完毕,调用
npm run tauri build
,得到对应的可执行文件、或者安装包。
但这仅限于简单的应用,如果你的应用变得复杂了、涉及到多窗口、或者出现性能问题,那么你就有必要对其了解的更加深入了。
这里首先提到的是tauri中的进程模型,和electron一样,tauri同样采取的多进程模型:
graph LR
A[Core]--Events & Commands1-->B[webview1]
A--Events & Commands2-->C[webview2]
A--Events & Commands3-->D[webview3]
多进程的好处简单来说就是让程序变得更加安全,不至于某个窗口崩溃导致整个程序直接崩溃,不理解的可以参考文章进程与线程。
比如你打开的浏览器中每个页面都对应一个进程,这也是为什么偶尔某个页面崩溃,不会导致整个浏览器崩溃的原因,只不过这样做的代价是会耗费更多的系统资源。
上图的Core
就是我们的rust代码所对应的那个进程,而下面的每个WebView
都对应一个窗口。
这一点非常重要!
这意味着你前端使用invoke
函数调用后端的rust代码,实际上是在进行“跨进程通信”,这导致两者之间传输的数据量不能过于庞大,否则会导致应用程序严重卡顿。
比如我曾试过将rust遍历得到的本地计算机两百多万个文件发送给前端处理,这直接就会导致程序卡死,因为它们之间是真的会实打实的复制数据进行传输,而不是在同一个进程中直接交换一下数据指针就行了。