一、背景與目標:為什麼做一個“非典型”的RSS閲讀器?
在信息爆炸的時代,RSS依然是高效獲取結構化內容的重要方式,但市面上主流閲讀器要麼功能冗餘(如集成社交屬性),要麼技術棧陳舊(依賴Electron導致內存佔用高、性能差)。我們希望打造一款簡約輕量、高效率、高性能、隱私安全的RSS閲讀器,核心需求包括:
- 智庫情報引擎:支持基於搜索引擎的信息抓取與RSS源訂閲。
- 由AI驅動的特色能力:自動翻譯、內容摘要、AI伴讀。
- 隱私與安全:數據本地化存儲,用户完全掌控隱私,不依賴第三方雲服務;
- 跨平台與高性能:跨Windows/macOS/Linux三端,適配低配置設備,保證流暢運行。
最終選擇 Rust+Web 的技術組合,這一選擇背後是對性能、開發效率與跨平台能力的深度權衡。
關於Saga Reader
基於Tauri開發的開源AI驅動的智庫式閲讀器(前端部分使用Web框架),能根據用户指定的主題和偏好關鍵詞自動從互聯網上檢索信息。它使用雲端或本地大型模型進行總結和提供指導,幷包括一個AI驅動的互動閲讀伴讀功能,你可以與AI討論和交換閲讀內容的想法。
這個項目我5月剛放到Github上(Github - Saga Reader),歡迎大家關注分享。🧑💻碼農🧑💻開源不易,各位好人路過請給個小星星💗Star💗。
核心技術棧:Rust + Tauri(跨平台)+ Svelte(前端)+ LLM(大語言模型集成),支持本地 / 雲端雙模式
關鍵詞:端智能,邊緣大模型;Tauri 2.0;桌面端安裝包 < 5MB,內存佔用 < 20MB。
運行截圖
二、技術選型:Rust+前端如何通過Tauri實現“1+1>2”?
1. 前端框架:Svelte的“輕量”哲學
傳統前端框架(如React/Vue)依賴運行時支持,產物體積大且存在多餘的性能開銷,而更現代化的Svelte框架通過編譯時轉換代碼,生成直接操作DOM的最小化JS包。在我們的項目中:
app/src/routes目錄下的頁面組件編譯後體積僅15KB(未壓縮),對比同複雜度的React應用小40%;- Svelte的響應式狀態管理(
$:自動追蹤依賴)與Tauri的IPC(進程間通信)天然契合。前端通過tauri.invoke調用Rust接口後,可直接更新響應式狀態(示例代碼見app/src/lib/store.ts)。
2. 後端核心:Rust的“安全+性能”雙保險
RSS閲讀器的核心瓶頸在於數據解析、網絡IO與本地存儲。Rust的 serde(序列化/反序列化)+ reqwest(HTTP客户端)+ sqlx(數據庫ORM)組合完美解決了這些問題:
serde配合自定義Deserialize實現,可兼容90%以上非標準Feed(代碼見crates/feed_api_rs/src/parser.rs);tokio異步運行時讓100+併發請求的延遲控制在200ms內;- Rust的零成本抽象(如
enum錯誤類型)讓前後端接口定義更嚴謹(crates/types/src/lib.rs定義了統一的FeedItem結構體)。
3. 跨平台橋樑:Tauri替代Electron的底層邏輯
選擇Tauri而非Electron的核心原因是資源佔用,我們不想讓用户因為一個工具應用消耗他的硬件資源以及寶貴的用户時間:
- Tauri基於系統原生WebView(如Windows的WebView2),而非捆綁Chromium,安裝包體積僅Electron應用的1/3(我們的Windows安裝包為18MB,同功能Electron應用約60MB);
- Tauri的IPC通信通過
tauri-plugin機制封裝,前端調用Rust接口時,參數自動序列化/反序列化(示例:app/src/lib/api/feed.ts中updateFeed函數調用tauri.invoke('update_feed', { url }),對應src-tauri/src/handlers.rs的update_feed函數); - 構建配置更靈活:通過
src-tauri/tauri.conf.json可定製各平台的打包參數(如Windows的圖標、macOS的簽名)。
三、關鍵實現:從“想法”到“可用”的技術細節
1. Rust插件開發:如何讓前端“調用”Rust能力?
項目中 crates/tauri-plugin-feed-api 是核心插件,它通過以下步驟暴露Rust功能給前端:
- 定義接口:在
src/lib.rs中使用tauri::command宏標記可調用函數(如fetch_feed(url: &str)); - 註冊插件:在
src-tauri/src/main.rs中通過tauri::Builder::plugin註冊插件,確保前端能通過tauri.invoke訪問; - 類型對齊:前端
types.d.ts(app/src/app.d.ts)需與Rust的crates/types/src/lib.rs結構體完全一致(如FeedItem的title、pub_date字段),避免通信時類型錯誤。
2. 前端性能優化:Svelte與Tailwind的“減法藝術”
- 按需加載:通過Vite的
import.meta.glob實現路由懶加載(app/src/routes/+page.svelte中動態導入子頁面); - 樣式隔離:Tailwind的
@apply指令配合Svelte的style標籤,避免全局樣式污染(app/src/app.css中定義基礎樣式,頁面組件內使用局部類名); - 狀態管理:
app/src/lib/store.ts中通過writable存儲當前選中的Feed,組件訂閲該狀態自動更新(對比Redux減少了30%樣板代碼)。
3. 跨平台兼容:三端“差異化”處理的底層邏輯
- 文件路徑:Rust使用
std::path::PathBuf處理不同系統的路徑分隔符(crates/recorder/src/storage.rs中get_db_path函數根據std::env::consts::OS動態拼接路徑); - 權限申請:Windows下需要管理員權限寫入
Program Files目錄,通過Tauri的before_quit鈎子檢查權限(src-tauri/src/hooks.rs中check_permission函數); - 通知功能:利用系統原生通知API(如macOS的
NSUserNotification、Windows的ToastNotification),通過tauri-plugin-notification實現跨平台調用(前端app/src/lib/utils/notify.ts封裝了統一接口)。
四、踩坑與解決方案:從“跑起來”到“穩定跑”
1. RSS解析的“非標”之痛
早期遇到部分Feed源返回帶 CDATA 標籤的描述字段,serde_xml_rs 默認無法解析。解決方案:
- 在
crates/feed_api_rs/src/parser.rs中自定義XmlDecoder,使用regex庫匹配CDATA標籤並提取內容; - 對解析失敗的Feed,記錄錯誤類型(如
InvalidXml、MissingField)並返回給前端提示用户(crates/types/src/error.rs定義了詳細的錯誤枚舉)。
2. Tauri IPC的“性能陷阱”
前端高頻調用Rust接口(如滾動加載時批量獲取歷史記錄)導致主線程阻塞。優化方案:
- 將耗時操作(如數據庫查詢)放入
tokio::spawn異步任務(src-tauri/src/handlers/history.rs中get_history函數使用async標記); - 限制單次IPC調用的參數大小(超過1MB的數據改為文件緩存,通過臨時文件路徑傳遞)。
3. 構建配置的“平台差異”
macOS打包時簽名失敗,原因是 tauri.conf.json 中 macOS.identity 配置錯誤。解決步驟:
- 通過
security find-identity -p codesigning命令獲取正確的簽名證書ID; - 在
src-tauri/tauri.conf.json中設置"identity": "ABCDEF123456",並添加"entitlements": "src-tauri/entitlements.plist"指定權限; - 參考Tauri官方文檔調整
build.macos字段。
五、總結:Rust+前端協同開發的“得與失”
得:
- 性能:Rust處理數據的效率是JS的5-10倍(如Feed解析耗時從500ms降至80ms);
- 體積:Tauri應用的安裝包比Electron小60%以上,更符合用户對“輕量工具”的期待;
- 可維護性:Rust的類型系統與前端TypeScript形成“雙保險”,減少運行時錯誤。
失:
- 學習成本:前端開發者需掌握Rust基礎(如所有權機制),後端開發者需理解前端構建流程(如Vite的
resolve.alias配置); - 調試複雜度:跨進程調試(前端調用Rust接口)需要同時監聽前端控制枱和Rust日誌(通過
tauri dev命令同時輸出兩端日誌)。
給開發者的建議:
- 優先用Rust處理計算密集型/IO密集型任務(如數據解析、網絡請求),前端專注UI交互;
- 統一前後端數據類型(推薦用TypeScript + Rust struct雙向生成);
- 善用Tauri的
beforeDevCommand和beforeBuildCommand鈎子(如app/vite.config.ts中配置beforeDevCommand: 'cargo build --package tauri-plugin-feed-api',自動編譯Rust插件)。
希望這篇實踐能為跨平台開發的同學提供參考,也歡迎在項目倉庫(saga-reader)提Issue討論更多細節!