Tauri:快速、跨平台桌面应用
在本教程中,我们将探索金牛座的,一个用于构建桌面应用程序的现代跨平台框架。年代trong>
内容:年代trong>
多年来,电子实际上是构建桌面应用程序的跨平台框架。Visual Studio Code、MongoDB Compass和Postman都是用这个框架构建的应用程序的很好的例子。Electron确实很棒,但是它有一些明显的缺点,这是其他一些现代框架已经克服的——Tauri就是其中最好的一个。
什么是金牛座?
Tauri是一个现代的框架,允许您使用熟悉的web技术(如HTML, CSS和JavaScript)在前端设计,开发和构建跨平台应用程序,同时利用强大的功能Rust编程语言在后台。
金牛座的是框架不可知论者。这意味着您可以将它与您选择的任何前端库一起使用——例如Vue、React、slvelte等等。另外,在基于tauri的项目中使用Rust是完全可选的。你可以只使用Tauri提供的JavaScript API来构建你的整个应用程序。这不仅可以很容易地构建一个新的应用程序,而且还可以使用你已经构建的web应用程序的代码库,并将其转变为本地桌面应用程序,而几乎不需要修改原始代码。
让我们看看为什么我们应该使用Tauri而不是Electron。
金牛座vs电子:一个快速比较
构建一个真正优秀的应用程序有三个重要元素:应用程序必须小巧、快速和安全。Tauri在这三个方面都优于Electron:
- Tauri产生的二进制文件要小得多。年代trong>你可以从Tauri发布的基准测试结果,甚至是超级简单的你好,世界!当使用Electron构建时,应用程序可以是一个巨大的大小(超过120 MB)。相比之下,同一个Tauri应用程序的二进制大小要小得多,不到2mb。在我看来,这是相当令人印象深刻的。
- Tauri应用程序执行得更快。年代trong>从上面提到的同一页中,你还可以看到Tauri应用程序的内存使用量可能是等效Electron应用程序的近一半。
- Tauri应用程序非常安全。年代trong>在Tauri网站上,你可以读到所有内置安全功能Tauri默认提供。但是我想在这里提到的一个值得注意的特性是,开发人员可以显式地启用或禁用某些api。这不仅让你的应用程序更安全,而且还减少了二进制大小。
创建一个笔记应用程序
在本节中,我们将构建一个简单的笔记应用程序,具有以下功能:
- 添加和删除注释
- 重命名笔记的标题
- 在Markdown中编辑笔记内容
- 在HTML中预览笔记的内容
- 将笔记保存到本地存储
- 将票据导入和导出到系统硬盘驱动器
你可以找到所有的GitHub上的项目文件.
开始
要开始使用Tauri,您首先需要安装Rust及其系统依赖项.它们根据用户的操作系统而有所不同,所以我不打算在这里探讨它们。请按照文档中有关操作系统的说明操作。
当你准备好了,在你选择的目录下,运行以下命令:
npm年代pan>创建tauri-app
这将指导您完成如下所示的安装过程:
$<年代pan class="token function">npm年代pan>我们希望<年代pan class="token builtin class-name">帮助年代pan>你和金牛一起创造了一些特别的东西<年代pan class="token operator">!年代pan>你可以选择一个更大的web技术社区支持的UI框架。这个工具可以让您快速入门。请访问https://tauri.app/查看我们的文档,如果你还没有设置好你的系统,请花点时间。你可能<年代pan class="token function">找到年代pan>https://tauri.app/v1/guides/getting-started/prerequisites按任意键继续<年代pan class="token punctuation">..年代pan>.?你的应用叫什么名字?我的笔记吗?窗口标题应该是什么?我的笔记?你想添加什么UI配方?create-vite<年代pan class="token punctuation">(年代pan>香草,vue,反应,苗条,preact,点燃<年代pan class="token punctuation">)年代pan>(年代pan>https://vitejs.dev/guide/<年代pan class="token comment"># scaffolding-your-first-vite-project)年代pan>?添加<年代pan class="token string">“@tauri-apps / api”年代pan>npm年代pan>包吗?是吗?您想使用哪个vite模板?react-ts<年代pan class="token operator">>>年代pan>初始化命令<年代pan class="token punctuation">(年代pan>年代<年代pan class="token punctuation">)年代pan>需要<年代pan class="token function">安装年代pan>create-vite@3.2.1可以继续吗?<年代pan class="token punctuation">(年代pan>y<年代pan class="token punctuation">)年代pan>y<年代pan class="token operator">>>年代pan>安装任何额外需要的依赖添加<年代pan class="token number">87年代pan>包,并经过审计<年代pan class="token number">88年代pan>包<年代pan class="token keyword">在年代pan>19世纪<年代pan class="token number">9年代pan>包裹正在寻找<年代pan class="token keyword">为年代pan>资金运行<年代pan class="token variable">`年代pan>npm年代pan>基金<年代pan class="token variable">`年代pan>为年代pan>发现细节<年代pan class="token number">0年代pan>漏洞补充道<年代pan class="token number">2年代pan>包,并经过审计<年代pan class="token number">90年代pan>包<年代pan class="token keyword">在年代pan>7 s<年代pan class="token number">10年代pan>包裹正在寻找<年代pan class="token keyword">为年代pan>资金运行<年代pan class="token variable">`年代pan>npm年代pan>基金<年代pan class="token variable">`年代pan>为年代pan>发现细节<年代pan class="token number">0年代pan>漏洞<年代pan class="token operator">>>年代pan>更新<年代pan class="token string">“package.json”年代pan>>>年代pan>运行<年代pan class="token string">“金牛座的init”年代pan>>年代pan>my-notes@0.0.0金牛座的<年代pan class="token operator">>年代pan>tauri init——app-name My - Notes——window-title My Notes——disti -dir<年代pan class="token punctuation">..年代pan>/dist——dev-path http://localhost:5173你的frontend dev命令是什么?·<年代pan class="token function">npm年代pan>你的前端构建命令是什么?·<年代pan class="token function">npm年代pan>运行构建<年代pan class="token operator">>>年代pan>更新<年代pan class="token string">“tauri.conf.json”年代pan>>>年代pan>运行最终命令<年代pan class="token punctuation">(年代pan>年代<年代pan class="token punctuation">)年代pan>安装完成。$<年代pan class="token builtin class-name">cd年代pan>我的笔记美元<年代pan class="token function">npm年代pan>运行tauri dev
请确保你的选择与我所做的匹配,这主要是搭建一个React应用程序与Vite和TypeScript支持,并安装Tauri API包。
先不要运行应用程序。首先,我们需要为我们的项目安装一些额外的包。在终端上运行以下命令:
npm年代pan>安装年代pan>@mantine/core @mantine/hooks @table /icons @emotion/react标记-反应
这将安装以下包:
- Mantine:一个功能齐全的React组件库
- 塔伯图标:超过3000像素完美的网页设计图标
- React的情感:用于React中的简单样式
- marked-react:用于渲染Markdown作为React组件使用标志着
现在我们准备测试应用程序,但在此之前,让我们看看项目是如何结构的:
my-notes/├─node_modules/├─public/├─src/│├─assets/││├─react.svg│├─css│├─index.css│├─main。│├─rammstein . exe。ts├─src-tauri /│├─图标/│├─src /│├─.gitignore│├─构建。│├─Cargo。来毫升│ └─ tauri.config.json ├─ .gitignore ├─ index.html ├─ package-lock.json ├─ package.json ├─ tsconfig.json ├─ tsconfig.node.json └─ vite.config.ts
这里最重要的是应用程序的React部分存储在src
目录,Rust和其他特定于tauri的文件存储在src-tauri
.我们在Tauri目录中唯一需要接触的文件是tauri.conf.json
,在那里我们可以配置应用程序。打开这个文件,找到allowlist
关键。将其内容改为:
“allowlist”年代pan>:年代pan>{年代pan>“对话框”年代pan>:年代pan>{年代pan>“保存”年代pan>:年代pan>真正的年代pan>,年代pan>“开放”年代pan>:年代pan>真正的年代pan>,年代pan>“问”年代pan>:年代pan>真正的年代pan>}年代pan>,年代pan>“fs”年代pan>:年代pan>{年代pan>“writeFile”年代pan>:年代pan>真正的年代pan>,年代pan>“readFile”年代pan>:年代pan>真正的年代pan>,年代pan>“范围”年代pan>:年代pan>[年代pan>“美元文档/ *”年代pan>,年代pan>“桌面/ *美元”年代pan>]年代pan>}年代pan>,年代pan>“路径”年代pan>:年代pan>{年代pan>“所有”年代pan>:年代pan>真正的年代pan>}年代pan>,年代pan>“通知”年代pan>:年代pan>{年代pan>“所有”年代pan>:年代pan>真正的年代pan>}年代pan>}年代pan>,年代pan>
在这里,出于安全原因,正如我上面提到的,我们只启用我们将在应用程序中使用的api。我们还限制了对文件系统的访问,只有两个例外-文档
而且桌面
目录。这将允许用户将他们的笔记导出到这些目录。
在关闭文件之前,我们还需要更改一件事。找到包
关键。在那把钥匙下,你会找到标识符
关键。将其值更改为com.mynotes.dev
.这在应用程序构建中是必需的,因为标识符必须是唯一的。
我想说的最后一点是,在最后窗户
键,你可以设置所有窗口相关的设置:
“windows”年代pan>:年代pan>[年代pan>{年代pan>“全屏”年代pan>:年代pan>假年代pan>,年代pan>“高度”年代pan>:年代pan>600年代pan>,年代pan>“可调整大小的年代pan>:年代pan>真正的年代pan>,年代pan>“标题”年代pan>:年代pan>“我的笔记”年代pan>,年代pan>“宽度”年代pan>:年代pan>800年代pan>}年代pan>]年代pan>
如你所见,标题
Key是根据您在安装期间给它的值为您设置的。
好,让我们最终启动应用程序我的笔记
目录下,执行以下命令:
npm年代pan>运行tauri dev
您需要等待一段时间,直到Tauri设置完成,所有文件都第一次编译完成。别担心。在后续的构建中,这个过程将会快得多。当Tauri准备好时,它会自动打开应用程序窗口。下图显示了您应该看到的内容。
注意:在应用程序在开发模式下运行或构建后,一个新的目标
目录创建在src-tauri
,其中包含所有已编译的文件。在开发模式下,它们被放置在调试
子目录,在构建模式下,它们被放置在释放
子目录。
好的,现在让我们根据需要调整文件。首先,删除index.css
而且App.css
文件。然后打开main.tsx
文件并将其内容替换为以下内容:
进口年代pan>反应年代pan>从年代pan>“反应”年代pan>进口年代pan>ReactDOM年代pan>从年代pan>“react-dom /客户端”年代pan>进口年代pan>{年代pan>MantineProvider年代pan>}年代pan>从年代pan>“@mantine /核心”年代pan>进口年代pan>应用程序年代pan>从年代pan>”。/应用程序年代pan>ReactDOM年代pan>.年代pan>createRoot年代pan>(年代pan>文档年代pan>.年代pan>getElementById年代pan>(年代pan>“根”年代pan>)年代pan>作为年代pan>HTMLElement年代pan>)年代pan>.年代pan>渲染年代pan>(年代pan><年代pan>反应年代pan>.年代pan>StrictMode年代pan>>年代pan><年代pan>MantineProvider年代pan>withGlobalStyles withNormalizeCSS<年代pan class="token operator">>年代pan><年代pan>应用程序年代pan>/年代pan>>年代pan><年代pan>/年代pan>MantineProvider年代pan>>年代pan><年代pan>/年代pan>反应年代pan>.年代pan>StrictMode年代pan>>年代pan>)年代pan>
这样就可以使用Mantine的组件了。
接下来,打开App.tsx
文件并将其内容替换为以下内容:
进口年代pan>{年代pan>useState<年代pan class="token punctuation">}年代pan>从年代pan>“反应”年代pan>进口年代pan>{年代pan>按钮年代pan>}年代pan>从年代pan>“@mantine /核心”年代pan>函数年代pan>应用程序年代pan>(年代pan>)年代pan>{年代pan>常量年代pan>[年代pan>数<年代pan class="token punctuation">,年代pan>setCount<年代pan class="token punctuation">]年代pan>=年代pan>useState年代pan>(年代pan>0年代pan>)年代pan>返回年代pan>(年代pan><年代pan>div<年代pan class="token operator">>年代pan><年代pan>按钮年代pan>onClick<年代pan class="token operator">=年代pan>{年代pan>(年代pan>)年代pan>= >年代pan>setCount年代pan>(年代pan>(年代pan>数年代pan>)年代pan>= >年代pan>数<年代pan class="token operator">+年代pan>1年代pan>)年代pan>}年代pan>>年代pan>数是<年代pan class="token punctuation">{年代pan>数<年代pan class="token punctuation">}年代pan><年代pan>/年代pan>按钮年代pan>>年代pan><年代pan>/年代pan>div<年代pan class="token operator">>年代pan>)年代pan>}年代pan>出口年代pan>默认的年代pan>应用程序年代pan>
现在,如果你看一下应用程序窗口,你应该看到以下内容:
通过单击按钮,确保应用程序正常运行。如果出现错误,您可能需要调试它。(见下注)
注意:当应用程序在开发模式下运行时,您可以通过右键单击应用程序窗口并选择打开DevTools<年代trong>检查年代trong>菜单上的。
创建基本应用程序功能
现在让我们创建应用程序的框架App.tsx
连同以下文件:
进口年代pan>{年代pan>useState<年代pan class="token punctuation">}年代pan>从年代pan>“反应”年代pan>进口年代pan>减价年代pan>从年代pan>“marked-react”年代pan>进口年代pan>{年代pan>ThemeIcon年代pan>,年代pan>按钮年代pan>,年代pan>CloseButton年代pan>,年代pan>开关年代pan>,年代pan>NavLink年代pan>,年代pan>Flex年代pan>,年代pan>网格年代pan>,年代pan>分频器年代pan>,年代pan>纸年代pan>,年代pan>文本年代pan>,年代pan>TextInput年代pan>,年代pan>文本区域年代pan>}年代pan>从年代pan>“@mantine /核心”年代pan>进口年代pan>{年代pan>useLocalStorage<年代pan class="token punctuation">}年代pan>从年代pan>“@mantine /挂钩”年代pan>进口年代pan>{年代pan>IconNotebook年代pan>,年代pan>IconFilePlus年代pan>,年代pan>IconFileArrowLeft年代pan>,年代pan>IconFileArrowRight年代pan>}年代pan>从年代pan>“@ table /图标”年代pan>进口年代pan>{年代pan>保存<年代pan class="token punctuation">,年代pan>开放<年代pan class="token punctuation">,年代pan>问<年代pan class="token punctuation">}年代pan>从年代pan>“@tauri-apps / api /对话框”年代pan>进口年代pan>{年代pan>writeTextFile<年代pan class="token punctuation">,年代pan>readTextFile<年代pan class="token punctuation">}年代pan>从年代pan>“@tauri-apps / api / fs”年代pan>进口年代pan>{年代pan>sendNotification<年代pan class="token punctuation">}年代pan>从年代pan>“@tauri-apps / api /通知”年代pan>函数年代pan>应用程序年代pan>(年代pan>)年代pan>{年代pan>常量年代pan>[年代pan>笔记<年代pan class="token punctuation">,年代pan>setNotes<年代pan class="token punctuation">]年代pan>=年代pan>useLocalStorage年代pan>(年代pan>{年代pan>关键<年代pan class="token operator">:年代pan>“我的笔记”年代pan>,年代pan>defaultValue<年代pan class="token operator">:年代pan>[年代pan>{年代pan>“标题”年代pan>:年代pan>“新笔记”年代pan>,年代pan>“内容”年代pan>:年代pan>""年代pan>}年代pan>]年代pan>}年代pan>)年代pan>常量年代pan>[年代pan>活跃的<年代pan class="token punctuation">,年代pan>setActive<年代pan class="token punctuation">]年代pan>=年代pan>useState年代pan>(年代pan>0年代pan>)年代pan>常量年代pan>[年代pan>标题<年代pan class="token punctuation">,年代pan>setTitle<年代pan class="token punctuation">]年代pan>=年代pan>useState年代pan>(年代pan>""年代pan>)年代pan>常量年代pan>[年代pan>内容<年代pan class="token punctuation">,年代pan>setContent<年代pan class="token punctuation">]年代pan>=年代pan>useState年代pan>(年代pan>""年代pan>)年代pan>常量年代pan>[年代pan>检查<年代pan class="token punctuation">,年代pan>setChecked<年代pan class="token punctuation">]年代pan>=年代pan>useState年代pan>(年代pan>假年代pan>)年代pan>常量年代pan>handleSelection年代pan>=年代pan>(年代pan>标题<年代pan class="token operator">:年代pan>字符串<年代pan class="token punctuation">,年代pan>内容<年代pan class="token operator">:年代pan>字符串<年代pan class="token punctuation">,年代pan>指数<年代pan class="token operator">:年代pan>数量年代pan>)年代pan>= >年代pan>{年代pan>setTitle年代pan>(年代pan>标题<年代pan class="token punctuation">)年代pan>setContent年代pan>(年代pan>内容<年代pan class="token punctuation">)年代pan>setActive年代pan>(年代pan>指数<年代pan class="token punctuation">)年代pan>}年代pan>常量年代pan>addNote年代pan>=年代pan>(年代pan>)年代pan>= >年代pan>{年代pan>笔记<年代pan class="token punctuation">.年代pan>拼接年代pan>(年代pan>0年代pan>,年代pan>0年代pan>,年代pan>{年代pan>标题<年代pan class="token operator">:年代pan>“新笔记”年代pan>,年代pan>内容<年代pan class="token operator">:年代pan>""年代pan>}年代pan>)年代pan>handleSelection年代pan>(年代pan>“新笔记”年代pan>,年代pan>""年代pan>,年代pan>0年代pan>)年代pan>setNotes年代pan>(年代pan>[年代pan>...年代pan>笔记<年代pan class="token punctuation">]年代pan>)年代pan>}年代pan>常量年代pan>deleteNote年代pan>=年代pan>异步年代pan>(年代pan>指数<年代pan class="token operator">:年代pan>数量年代pan>)年代pan>= >年代pan>{年代pan>让年代pan>deleteNote<年代pan class="token operator">=年代pan>等待年代pan>问年代pan>(年代pan>“你确定要删除这张便条吗?”年代pan>,年代pan>{年代pan>标题<年代pan class="token operator">:年代pan>“我的笔记”年代pan>,年代pan>类型<年代pan class="token operator">:年代pan>“警告”年代pan>,年代pan>}年代pan>)年代pan>如果年代pan>(年代pan>deleteNote<年代pan class="token punctuation">)年代pan>{年代pan>笔记<年代pan class="token punctuation">.年代pan>拼接年代pan>(年代pan>指数<年代pan class="token punctuation">,年代pan>1年代pan>)年代pan>如果年代pan>(年代pan>活跃的<年代pan class="token operator">> =年代pan>指数<年代pan class="token punctuation">)年代pan>{年代pan>setActive年代pan>(年代pan>活跃的<年代pan class="token operator">> =年代pan>1年代pan>?年代pan>活跃的<年代pan class="token operator">-年代pan>1年代pan>:年代pan>0年代pan>)年代pan>}年代pan>如果年代pan>(年代pan>笔记<年代pan class="token punctuation">.年代pan>长度年代pan>> =年代pan>1年代pan>)年代pan>{年代pan>setContent年代pan>(年代pan>笔记<年代pan class="token punctuation">[年代pan>指数<年代pan class="token operator">-年代pan>1年代pan>]年代pan>.年代pan>内容年代pan>)年代pan>}年代pan>其他的年代pan>{年代pan>setTitle年代pan>(年代pan>""年代pan>)年代pan>setContent年代pan>(年代pan>""年代pan>)年代pan>}年代pan>setNotes年代pan>(年代pan>[年代pan>...年代pan>笔记<年代pan class="token punctuation">]年代pan>)年代pan>}年代pan>}年代pan>返回年代pan>(年代pan><年代pan>div<年代pan class="token operator">>年代pan><年代pan>网格年代pan>长米<年代pan class="token operator">=年代pan>{年代pan>