项目简介
前阵子我开源了一个项目——Huntly,它是一个信息管理工具,不仅可以自托管,也可以通过客户端在本地运行。
先简单介绍一下它是个什么样的东西,它有以下功能:
- RSS 订阅。
- 网页收藏,自动/手动保存浏览过的网页,随后以保存、稍后读、收藏或存档的方式将其保存。
- 推文保存,针对推特网站有特殊的处理,会自动保存请求过的推特 timeline,记录是否浏览过,在 huntly 中你甚至可以用更方便的方式重新查看这些推文。
- 内容全文搜索,可以从标题、内容、类型、收藏方式等维度进行搜索。
- 连接其他服务,目前支持 GitHub,所以它也是一个 Github stars 管理工具。
系统截图
感兴趣的读者朋友可以试用以下。
主要技术栈
以上只是简单介绍一下这个项目,写这篇文章主要是为了分享一下其中所使用到的技术。
这是一个给自己用的服务,不涉及高并发大数据等场景,也就不存在什么高深的技术,不过它用到的技术栈却还算丰富,可以说是麻雀虽小五脏俱全。
通过阅读这个项目的源码,你无法成为一个大师,但是却能对其中用到的很多技术有一个快速的了解。
这个项目用到的主要技术栈有:
- Spring Boot
- React
- Lucene
- SQLite
- Tauri
使用到的编程语言有:
- Java
- TypeScript
- Rust
Spring Boot 服务端
服务端采用简单的单体架构,如图:
采用 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 前端
样式方面,采用了 MUI
和 TailwindCSS
混用,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 可以减少代码量。
表单管理,采用了 formik
和 yup
组件,formik 很灵活,可以和各种 UI 框架结合使用,搭配 yup 验证表单。
还用到一些好用的小组件,如:moment
、react-beautiful-dnd
、react-photo-view
等,具体使用请看源码。
Tauri 客户端
其实一开始采用的是 electron,还可以在 React 前端中看到部分 electron 的代码,最后觉得在客户端展示原本是网站的界面有些多余,它无法利用浏览器上的各种插件,不符合个人的使用习惯,所以改用了 Tauri,Tauri 打包的体积比 electron 要小很多,因为它不自带浏览器内核。
最终的客户端包含一个服务端设置界面、自动启动和托盘图标。当然,如果想把 Huntly 的前端界面在其中显示,让其看起来更像一个客户端是并不需要新增什么代码的,只是在这个场景下,我认为没有必要。
将 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。