使用 Spring Boot、React、Tauri 开发桌面客户端,开源项目 Huntly 让你轻松掌握这些技术

3,450 阅读4分钟

项目简介

前阵子我开源了一个项目——Huntly,它是一个信息管理工具,不仅可以自托管,也可以通过客户端在本地运行。

先简单介绍一下它是个什么样的东西,它有以下功能:

  • RSS 订阅。
  • 网页收藏,自动/手动保存浏览过的网页,随后以保存、稍后读、收藏或存档的方式将其保存。
  • 推文保存,针对推特网站有特殊的处理,会自动保存请求过的推特 timeline,记录是否浏览过,在 huntly 中你甚至可以用更方便的方式重新查看这些推文。
  • 内容全文搜索,可以从标题、内容、类型、收藏方式等维度进行搜索。
  • 连接其他服务,目前支持 GitHub,所以它也是一个 Github stars 管理工具。

系统截图

Pasted image 20230426160044.png

Pasted image 20230426160125.png

感兴趣的读者朋友可以试用以下。

主要技术栈

以上只是简单介绍一下这个项目,写这篇文章主要是为了分享一下其中所使用到的技术。

这是一个给自己用的服务,不涉及高并发大数据等场景,也就不存在什么高深的技术,不过它用到的技术栈却还算丰富,可以说是麻雀虽小五脏俱全。

通过阅读这个项目的源码,你无法成为一个大师,但是却能对其中用到的很多技术有一个快速的了解。

这个项目用到的主要技术栈有:

  • Spring Boot
  • React
  • Lucene
  • SQLite
  • Tauri

使用到的编程语言有:

  • Java
  • TypeScript
  • Rust

Spring Boot 服务端

服务端采用简单的单体架构,如图:

Pasted image 20230426160342.png

采用 JPA 操作数据库,默认使用 SQLite 数据库,使用 Lucene 组件和 IK 分词器来进行全文索引。

使用 Springfox 提供 OpenApi 文档,前端使用 OpenAPI-Generator 工具生成 API 调用代码。

使用 frontend-maven-plugin 插件将 React 前端资源打包到 Jar 包中。

将前端资源打包到 Jar 包中,需要处理好前端 Url 的路由映射,得益于 Spring Boot 强大的路由规则,新建一个 ReactAppController 即可,下面的代码将 /api 开头以外的请求都交给前端的 index.html 处理,以实现前端的正确路由。

@Controller  
@ApiIgnore  
public class ReactAppController {  
    @RequestMapping(value = {"/", "/{x:[\\w\\-]+}", "/{x:^(?!api$).*$}/**/{y:[\\w\\-]+}"})  
    public String getIndex() {  
        return "/index.html";  
    }  
}

React 前端

样式方面,采用了 MUITailwindCSS 混用,MUI 提供了丰富的组件,TailwindCSS 也能很大程度上提升样式编写效率。

接口方面,在 package.json 中添加 api-generate 脚本用于生成 api 调用代码,调用时本地开发服务端必须为运行状态。

"scripts": {  
  "api-generate": "cd ./src/api/ && openapi-generator-cli generate -i http://localhost:8080/v3/api-docs -g typescript-axios -o ."
}

数据查询,采用了 react-query 组件,对于简单的应用还不需要用到状态管理,使用 react-query 可以减少代码量。

表单管理,采用了 formikyup 组件,formik 很灵活,可以和各种 UI 框架结合使用,搭配 yup 验证表单。

还用到一些好用的小组件,如:momentreact-beautiful-dndreact-photo-view 等,具体使用请看源码。

Tauri 客户端

其实一开始采用的是 electron,还可以在 React 前端中看到部分 electron 的代码,最后觉得在客户端展示原本是网站的界面有些多余,它无法利用浏览器上的各种插件,不符合个人的使用习惯,所以改用了 Tauri,Tauri 打包的体积比 electron 要小很多,因为它不自带浏览器内核。

最终的客户端包含一个服务端设置界面、自动启动和托盘图标。当然,如果想把 Huntly 的前端界面在其中显示,让其看起来更像一个客户端是并不需要新增什么代码的,只是在这个场景下,我认为没有必要。

Pasted image 20230426163013.png

将 Spring Boot Fat Jar、JRE11 打包进客户端,最终只有不到 120MB,是一个完全可以接受的大小,下载地址:Release v0.3.5 · lcomplete/huntly · GitHub

采用 jlink 命令来打包 JRE:

jlink --module-path $JAVA_HOME/jmods --add-modules java.compiler,java.sql,java.naming,java.management,java.instrument,java.rmi,java.desktop,jdk.internal.vm.compiler.management,java.xml.crypto,java.scripting,java.security.jgss,jdk.httpserver,java.net.http,jdk.naming.dns,jdk.crypto.cryptoki,jdk.unsupported --verbose --strip-debug --compress 2 --no-header-files --no-man-pages --output jre11

Tauri 是一个新兴的客户端框架,它相比 electron 有一些优势,但目前还不算稳定,这点需要注意。

项目构建

采用 GitHub Actions 来进行完整的构建,具体请查看开源代码 Huntly workflows