上次写完阅读器的设计思路之后,我第二天就开始动手做桌面版了。
一句话总结:把软件交到别人手里,比写软件本身难多了。
为什么要做桌面版
原因特别简单——我想让同学双击 exe 就能用。
我原来的 web 版是这个架构:
- 后端:Express + Axios + Cheerio
- 前端:React
- 部署:Docker
自己用完全没问题。但要发给不写代码的同学,我得先教他们装 Node.js,或者教他们装 Docker,然后还得打开终端敲命令。
这不现实。我一个舍友连压缩包都不会解。
所以必须打包成 exe。双击运行,别的什么都不用管。
Electron vs Tauri
能做桌面端 exe 的框架,第一个想到的肯定是 Electron。但 Electron 有个我接受不了的问题——体积太大。一个什么都没写的 hello world 打包出来就上百 MB。
为什么?因为 Electron 给每个应用都塞了一个完整的 Chromium 浏览器。
Tauri v2 的思路完全相反。它不塞浏览器,直接调用 Windows 系统自带的 WebView2。前端还是用 React 写,但后端从 Node.js 换成了 Rust。
| Electron | Tauri v2 | |
|---|---|---|
| 打包体积 | 100MB+ | 14MB |
| 后端语言 | Node.js | Rust |
| 浏览器引擎 | 自带 Chromium | 系统 WebView2 |
| 内存占用 | 高 | 低 |
14MB 什么概念?QQ 安装包快 200MB 了。一个带三个书源的桌面阅读器,体积只有 QQ 的百分之七。
但 Tauri 有个门槛:后端要用 Rust 重写。
从零开始写 Rust
我之前完全没碰过 Rust,只知道它是「系统级语言」「安全」「难学」。
书源的逻辑全在后端——搜索、抓取目录、解析章节内容。原来在 Node.js 里是这样:
1 | Axios → 发 HTTP 请求 |
到了 Rust 这边,每一个都得找对应的库:
1 | reqwest → HTTP 请求 |
Rust 的语法倒不是最难的。所有权、借用、生命周期确实需要适应,但 Rust 编译器报错极其友好——不仅告诉你怎么错了,还会建议怎么改。很多时候顺着编译器的提示就能把代码改对。
真正折磨人的是 Windows 工具链。
Win11 预览版上的地狱体验
我先装了 Rust 的 GNU 工具链。代码编译通过,生成了 exe。双击运行——
没反应。
不是报错,是双击之后什么都没发生。用命令行跑了一下,提示 os error 193——不是有效的 Win32 应用程序。文件格式明明是对的,但 Windows 就是不认。
只能换成 MSVC 工具链。然后问题又来了:
1 | Git 自带的 link.exe 和 MSVC 的链接器重名了 |
我盯着那个报错看了五分钟才反应过来——它用的根本不是微软的链接器。
最后装了 Visual Studio 的 C++ 构建工具,终于能正常编译了。
这些东西跟写代码一点关系都没有,但占了我差不多一半的开发时间。
三个书源的 Rust 实现
书源的设计和 web 版完全一样,每个书源实现三个方法,由一个路由器统一分发:
1 | search_books() → 搜索书籍 |
1 | ┌─→ guangyu(光遇 API) |
光遇 API —— 最省心,但爱挂
JSON 接口,数据格式规整,reqwest 拿到响应直接反序列化就完了。
但它有个毛病:API 服务器不稳定,经常某个域名挂了。我设了七个域名做 fallback,一个超时自动切下一个。
笔趣阁 —— 最折腾
GBK 编码的 HTML,搜索还是 POST 表单。Rust 这边要:
- 把中文关键词编码成 GBK 字节
- 拼到表单里发 POST
- 收到响应再把 GBK 字节解码回来
- 解析 HTML 提取结果
Node.js 里 fetch + iconv-lite 两行就搞定的事,Rust 里写了整整一个函数。
而且 Rust 的 regex 不支持反向引用。之前匹配成对 HTML 标签的正则 `<(script).*?</\1>` 直接报错,得改成显式的标签名:
1 | // Rust 不允许反向引用,只能显式列出标签名 |
七星阁 —— 脏数据真多
UTF-8 编码,省了编解码这一步。但章节内容里的脏数据太多了:
- 「本章未完,请翻下一页」
- 「第(1/3)页」
[玄幻]之类的分类前缀- 随机插入的广告文案
清理数据的正则代码比抓取数据的代码还多。 正则写多了之后才发现,做爬虫最难的从来不是发请求,是把别人乱七八糟的 HTML 洗成干净文本。
前后端通信的变化
web 版的前后端通信就是标准的 HTTP:
1 | // web 版 |
Tauri 版变成了进程间通信:
1 | // Tauri 版 |
这个改动对前端来说几乎是透明的。 除了把 fetch 换成 invoke,其他逻辑一行没改。这也是 Tauri 设计得好——前端开发者几乎感知不到后端的切换。
最大的感受
整个项目做完,我最大的感受不是「Rust 真难」也不是「Tauri 真香」——
把软件交到别人手里,比写软件本身难多了。
功能我在 web 版就写好了。搜索、目录、阅读器、日夜间模式,web 版全都有。
但为了让别人能 双击运行,我做的事情包括:
- 把后端从 Node.js 迁移到 Rust
- 折腾 Windows 工具链
- 处理三个不同书源的各种编码和格式
- 用 GitHub Releases 发布 exe
- 写面向小白用户的图文 README
这些全都不是「功能开发」,但每一项都不可或缺。没有它们,软件就只是我电脑上的 localhost:3000,别人根本看不见。
我以前觉得软件工程最难的是写代码。现在发现,代码只是冰山在水面上的那一角。水面之下是分发、部署、文档、兼容性——这些才是决定一个软件能不能真正「存在」的东西。
软件截图


接下来要做的事
目前 v0.1.0 已经发在 GitHub Releases 上了,14MB 的单 exe,下载双击就能用。
但离「好用」还有距离,接下来几天集中做三件事:
- 书源扩展 — 现有的三个书源覆盖率太低,搜冷门书基本搜不到。至少再补几个主流网文源。
- 书架和历史记录 — 现在每次打开软件都要重新搜索,没有任何持久化。下一步用 SQLite 把阅读进度、书架收藏存到本地。
- 阅读体验优化 — 现在的字号只有三档,翻页也没有动画。至少要加上自定义字号、行距、翻页动画。
等这些做完,v1.0 才算真的能用。
















