一、项目背景:当AI阅读遇到跨平台需求

Saga Reader(麒睿智库)是一款基于AI技术的轻量级跨平台阅读器,核心功能涵盖RSS订阅、内容智能抓取、AI内容处理(如翻译、摘要)及本地存储。项目采用Rust(后端)+Svelte(前端)+Tauri(跨平台框架)的技术组合,目标是在老旧设备上实现"低于10MB内存占用"的极致性能,同时提供流畅的用户交互体验。关于Saga Reader的渊源,见《开源我的一款自用AI阅读器,引流Web前端、Rust、Tauri、AI应用开发》

关于Saga Reader

基于Tauri开发的开源AI驱动的智库式阅读器(前端部分使用Web框架),能根据用户指定的主题和偏好关键词自动从互联网上检索信息。它使用云端或本地大型模型进行总结和提供指导,并包括一个AI驱动的互动阅读伴读功能,你可以与AI讨论和交换阅读内容的想法。

这个项目我5月刚放到Github上(Github - Saga Reader),欢迎大家关注分享。‍码农‍开源不易,各位好人路过请给个小星星Star

核心技术栈:Rust + Tauri(跨平台)+ Svelte(前端)+ LLM(大语言模型集成),支持本地 / 云端双模式

关键词:端智能,边缘大模型;Tauri 2.0;桌面端安装包 < 5MB,内存占用 < 20MB。

功能架构

graph TD
A[前端架构] --> B[组件层]
A --> C[状态管理层]
A --> D[工具层]
A --> E[构建与运行时]

B --> B1[UI组件]
B --> B2[通用组件]
B1 --> B11[订阅列表组件]
B1 --> B12[阅读详情组件]
B1 --> B13[设置面板组件]
B2 --> B21[Markdown渲染组件]
B2 --> B22[上下文菜单组件]
B2 --> B23[保存操作面板组件]

C --> C1[Writable Store]
C --> C2[Derived Store]
C --> C3[Readable Store]
C1 --> C11[用户配置]
C2 --> C21[当前订阅]
C3 --> C31[加载状态]

D --> D1[国际化]
D --> D2[主题管理]
D --> D3[实用工具]
D --> D4[混合API]

E --> E1[Vite构建工具]
E --> E2[Svelte编译时优化]
E --> E3[Tauri运行时环境]

核心业务流程图

sequenceDiagram
participant Scrap as Scrap模块(Rust)
participant Intelligent as Intelligent模块(Rust)
participant Recorder as Recorder模块(Rust)
participant TauriEvent as Tauri事件
participant ReadableStore as Readable Store(前端)
participant DerivedStore as Derived Store(前端)
participant UI as 前端UI组件

Scrap->>Intelligent: 传递抓取内容
Intelligent->>Recorder: 传递AI处理结果(翻译/摘要)
Recorder->>TauriEvent: 触发"article-updated"事件<mcfile name="lib.rs" path="crates/recorder/src/lib.rs"></mcfile>
TauriEvent->>ReadableStore: 前端监听事件(listenArticleUpdate)<mcfile name="tauri-api.ts" path="app/src/lib/tauri-api.ts"></mcfile>
ReadableStore->>DerivedStore: 更新currentFeed Store
DerivedStore->>UI: 触发Svelte响应式更新($:块)<mcfile name="Reader.svelte" path="app/src/routes/Reader.svelte"></mcfile>
UI->>UI: 仅更新受影响DOM(如翻译进度条、内容区域)

运行截图

二、技术选型:为什么选择Svelte 5 + Tauri?

传统Electron+React方案在桌面应用中常见,但存在两大痛点:

  1. 性能瓶颈:Electron基于Chromium内核,内存占用普遍在50MB以上;React的虚拟DOMdiff在复杂状态变更时易产生性能损耗。
  2. 开发复杂度:React需要额外引入Redux/MobX等状态管理库,增加了学习成本和代码体积。

Svelte 5与Tauri的组合完美解决了这些问题:

  • Tauri基于Rust开发,运行时仅需MB级内存,且通过tauri-plugin-feed-api插件实现前端与Rust模块的高效通信;
  • Svelte作为编译时框架,在构建阶段将响应式逻辑转换为直接操作真实DOM的代码,避免了虚拟DOM的运行时开销,天然支持细粒度更新;
  • Svelte 5的内置状态管理方案(Svelte Store)无需额外依赖,语法简洁(如$:响应式声明),大幅降低开发复杂度。

三、状态管理实战:从多模块协作到UI更新的全链路优化

3.1 技术难点:跨模块状态同步的复杂性

Saga Reader的业务流程涉及多个模块协作:

scrap模块(内容抓取)→ intelligent模块(AI处理)→ recorder模块(存储)→ 前端UI(展示)

每个环节都需要状态同步,具体挑战包括:

  • 跨进程通信:前端(Svelte)与后端(Rust)通过Tauri插件通信,需处理异步调用的状态同步;
  • 多组件依赖:订阅列表、阅读详情、设置面板等组件需共享用户配置(如主题、语言)和内容状态(如未读计数);
  • 性能敏感:AI处理可能产生高频状态变更(如实时翻译进度),需避免不必要的UI重渲染。

3.2 Svelte 5的解决方案:Store + 响应式系统的组合拳

3.2.1 核心工具:Svelte Store的分层设计

项目采用三级Store结构管理状态:

项目采用writable(可写)→ derived(派生)→ readable(只读)三级Store结构,精准覆盖不同状态类型。以下是核心实现(参考app/src/lib/store.ts设计):

// 1. 持久化配置Store(writable)
import { writable } from 'svelte/store';
import { localStorage } from '@tauri-apps/plugin-storage'; // 初始值从本地存储加载
const loadConfig = async () => {
const config = await localStorage.get('userConfig');
return config || { theme: 'light', fontSize: 14, lang: 'zh' };
}; export const userConfig = writable({ theme: 'light', fontSize: 14, lang: 'zh' });
// 自动同步到本地存储
userConfig.subscribe(async (value) => {
await localStorage.set('userConfig', value);
await localStorage.save();
}); // 2. 派生内容状态Store(derived)
import { derived } from 'svelte/store';
import { activeFeedId } from './feedStore';
import { allFeeds } from './dataStore'; export const currentFeed = derived(
[activeFeedId, allFeeds],
([$activeFeedId, $allFeeds]) => {
return $allFeeds.find(feed => feed.id === $activeFeedId);
}
); // 3. 异步操作状态Store(readable)
import { readable } from 'svelte/store';
import { tauri } from '@tauri-apps/api'; export const loadingStatus = readable(false, (set) => {
let isLoading = false;
// 监听Rust模块的"抓取开始"事件
const onFetchStart = () => { isLoading = true; set(true); };
// 监听Rust模块的"抓取完成"事件
const onFetchEnd = () => { isLoading = false; set(false); }; tauri.listen('fetch-start', onFetchStart);
tauri.listen('fetch-end', onFetchEnd); // 清理函数
return () => {
tauri.unlisten('fetch-start', onFetchStart);
tauri.unlisten('fetch-end', onFetchEnd);
};
});

设计逻辑

  • writable Store:通过Tauri的localStorage插件实现配置持久化,订阅器自动同步变更,避免手动调用存储API;
  • derived Store:基于多个基础Store(如当前选中订阅ID和所有订阅列表)动态计算派生状态,仅当任一依赖变化时触发更新;
  • readable Store:封装Tauri事件监听逻辑,统一管理异步操作的加载状态(如内容抓取、AI处理),避免事件监听器泄漏。

3.2.2 细粒度更新:避免无效渲染的关键

Svelte的响应式系统通过$:标记自动追踪依赖,仅当依赖变量变化时更新相关代码块。例如:

Svelte的$:响应式声明通过编译时依赖分析,自动追踪变量的使用场景,仅在依赖变更时执行代码块。以app/src/routes/Reader.svelte的AI翻译进度更新为例:

<script>
import { currentFeed } from '$lib/store';
import { translateWithLLM } from '$lib/ai-service'; let translationProgress = 0;
let translatedContent = ''; // 响应式块:仅当currentFeed变化时执行
$: if ($currentFeed?.content) {
// 重置进度
translationProgress = 0;
translatedContent = '';
// 调用AI翻译(模拟异步流)
translateWithLLM($currentFeed.content).then((stream) => {
for await (const chunk of stream) {
translatedContent += chunk.text;
translationProgress = chunk.progress;
}
});
}
</script> <div class="reader-container">
<!-- 仅content变化时更新 -->
<article class="original-content">{$currentFeed?.content}</article> <!-- 仅translatedContent变化时更新 -->
<article class="translated-content">{$translatedContent}</article> <!-- 仅translationProgress变化时更新 -->
{#if translationProgress > 0}
<progress
value={translationProgress}
max="100"
class="translation-progress"
/>
{/if}
</div>

性能优势

  • 传统框架(如React)需手动通过useMemo/useCallback优化,Svelte通过编译时分析自动实现;
  • 在AI翻译的高频进度更新(50次/秒)中,仅progress组件和translated-content区域会被重新渲染,其他DOM节点保持稳定。根据docs/Introduction-of-the-solution-zh.md的实测数据,此机制使列表滚动流畅度提升30%,复杂表单提交延迟降低25%。

3.2.3 与Tauri的协同:状态同步的最后一公里

Rust的recorder模块完成内容存储后,通过Tauri事件通知前端:

// Rust端:存储完成后触发事件
pub fn save_article(article: Article) -> Result<(), Error> {
// 存储逻辑...
// 触发Tauri事件,通知前端更新
tauri::event::emit_all("article-updated", article)?;
Ok(())
}

前端通过readable Store监听事件并更新状态:

import { tauri } from '@tauri-apps/api';
import { currentFeed } from '$lib/store'; // 监听"article-updated"事件
export const listenArticleUpdate = () => {
tauri.listen('article-updated', (event) => {
const updatedArticle = event.payload as Article;
// 更新currentFeed Store(触发UI自动刷新)
currentFeed.update(feed => {
if (feed?.id === updatedArticle.feedId) {
feed.articles = feed.articles.map(art =>
art.id === updatedArticle.id ? updatedArticle : art
);
}
return feed;
});
});
};

优势

  • 避免手动调用setStatedispatch,通过Store的订阅机制自动同步;
  • 事件驱动模式解耦前后端,Rust模块无需关心前端状态结构,仅需传递基础数据。

四、性能与体验的双重提升:Svelte的"编译时优化"魔法

4.1 运行时性能:真实DOM操作 vs 虚拟DOM

Svelte在构建阶段将组件编译为直接操作真实DOM的代码,避免了React的虚拟DOM diff开销。根据docs/Introduction-of-the-solution-zh.md的对比测试:

  • 内存占用:Svelte+Tauri方案(≤10MB) vs Electron+React(≥50MB);
  • 渲染延迟:复杂列表渲染延迟从80ms降至50ms,滚动流畅度提升30%。

4.2 开发体验:简洁语法与零依赖

Svelte的状态管理无需额外库(如Redux的dispatch/reducer),通过writable/derived/readable即可完成90%的状态管理需求。开发团队反馈:"实现相同功能的代码量比React+Redux减少40%,调试状态变更的复杂度降低50%。"。

4.3 构建效率:Vite集成的极速体验

项目vite.config.ts中集成了Svelte插件,配合Vite的HMR(热更新),修改状态管理代码后,UI更新耗时仅200ms左右,极大提升了开发效率。

五、总结:Svelte 5 + Tauri,复杂应用的高效解

Saga Reader的实践证明,Svelte 5的状态管理方案在跨平台应用中具备高适应性低维护成本

  • 技术选型:Svelte的编译时优化与Tauri的轻量级运行时完美互补,适合对性能敏感的桌面应用;
  • 状态设计:三级Store体系(writable→derived→readable)可覆盖95%以上的状态类型,建议优先采用;
  • 协同优化:与Tauri的事件驱动同步机制,是解决跨进程状态一致性的高效方案。

未来可探索Svelte 5的context API优化深层组件状态传递,或结合Rust的tokio异步运行时进一步降低跨进程通信延迟。对于希望兼顾开发效率与运行性能的团队,Svelte 5+Tauri是值得优先尝试的技术组合。

Svelte 5状态管理实战:基于Tauri框架的AI阅读器Saga Reader开发实践的更多相关文章

  1. 基于 Angularjs&Node.js 云编辑器架构设计及开发实践

    基于 Angularjs&Node.js 云编辑器架构设计及开发实践 一.产品背景 二.总体架构 1. 前端架构 a.前端层次 b.核心基础模块设计 c.业务模块设计 2. Node.js端设 ...

  2. Vue3 企业级优雅实战 - 组件库框架 - 7 组件库文档的开发和构建

    该系列已更新文章: 分享一个实用的 vite + vue3 组件库脚手架工具,提升开发效率 开箱即用 yyg-cli 脚手架:快速创建 vue3 组件库和vue3 全家桶项目 Vue3 企业级优雅实战 ...

  3. 基于VUE框架 与 其他框架间的基本对比

    基于VUE框架的基本描述 与 其他框架间的基本对比 2018-11-03  11:01:14 A B React React 和 Vue 有许多相似之处,它们都有: 使用 Virtual DOM 提供 ...

  4. vue创建状态管理(vuex的store机制)

    1:为什么说要是永远状态管理 在使用 Vue 框架做单页面应用时,我们时常会遇到传值,组件公用状态的问题.(子父间传值文章传送门) ,如果是简单的应用,兄弟组件之间通信还能使用 eventBus 来作 ...

  5. Vue之状态管理(vuex)与接口调用

    Vue之状态管理(vuex)与接口调用 一,介绍与需求 1.1,介绍 1,状态管理(vuex) Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态 ...

  6. 基于ssh框架web示例

    基于ssh框架web示例 介绍 Spring Boot Web 开发非常简单,该示例包括包括目前web开发基本都需要用到的内容 - 序列化(json)输出 - 过滤器(filters) - 监视器(l ...

  7. 基于JSP的RSS阅读器的设计与实现

    阅读器访问地址:http://easyrss.tk/,欢迎体验! 阅读导览 一.    概述  二.    设计的基本概念和原理 三.    设计方案 四.    主要源代码 五.    阅读器使用说 ...

  8. 基于cookie的用户登录状态管理

    cookie是什么 先来花5分钟看完这篇文章:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Cookies 看完上文,相信大家对cookie已经有 ...

  9. 通过Dapr实现一个简单的基于.net的微服务电商系统(五)——一步一步教你如何撸Dapr之状态管理

    状态管理和上一章的订阅发布都算是Dapr相较于其他服务网格框架来讲提供的比较特异性的内容,今天我们来讲讲状态管理. 目录:一.通过Dapr实现一个简单的基于.net的微服务电商系统 二.通过Dapr实 ...

  10. 文献综述十八:基于SSH框架的进销存管理系统设计与实现

    一.基本信息 标题:基于SSH框架的进销存管理系统设计与实现 时间:2017 出版源:内蒙古科技与经济 文件分类:对框架的研究 二.研究背景 进销存管理系统在各企业中广泛应用,使用SSH框架,很大程度 ...

随机推荐

  1. 2个月搞定计算机二级C语言——真题(8)解析

    1. 前言 本篇我们讲解2个月搞定计算机二级C语言--真题8 2. 程序填空题 2.1 题目要求 2.2 提供的代码 #include <stdio.h> #define N 3 #def ...

  2. Docker镜像(image)详解

    如果曾经做过 VM 管理员,则可以把 Docker 镜像理解为 VM 模板,VM 模板就像停止运行的 VM,而 Docker 镜像就像停止运行的容器:而作为一名研发人员,则可以将镜像理解为类(Clas ...

  3. osmts:OERV之一站式管理测试脚本

      最近团队里面实习的小伙伴开发了一个新的项目,可以用来一键式运行各种测试脚本并且完成数据总结,我也尝试部署了一下,遇到了一些问题,接下来一起解析一下这个项目.   首先是获取osmts git cl ...

  4. 【Linux】3.10 进程管理(重点)

    进程管理 1. 进程管理基础 在Linux中,每个执行的程序(代码)都称为一个进程.每个进程都分配一个ID号 每一个进程,都会对应一个父进程,而这个父进程可以复制多个子进程.例如www服务器. 每个进 ...

  5. 【软件】解决奥林巴斯生物显微镜软件OlyVIA提示“不支持您使用的操作系统”安装中止的问题

    [软件]解决奥林巴斯生物显微镜软件OlyVIA提示"不支持您使用的操作系统"安装中止的问题 零.问题 资源在文末 问题如下,从奥林巴斯生物显微镜软件官网下载地址:https://l ...

  6. 一文速通 Python 并行计算:05 Python 多线程编程-线程的定时运行

    一文速通 Python 并行计算:05 Python 多线程编程-线程的定时运行 摘要: 本文主要讲述了 Python 如何实现定时任务,主要有四种方式:通过 threading.Timer 类.通过 ...

  7. Excel百万数据如何快速导入?

    前言 今天要讨论一个让无数人抓狂的话题:如何高效导入百万级Excel数据. 去年有家公司找到我,他们的电商系统遇到一个致命问题:每天需要导入20万条商品数据,但一执行就卡死,最长耗时超过3小时. 更魔 ...

  8. hexo搭建博客记录

    这是一次hexo搭建博客并引入archer主题的使用记录. 环境准备 首先是hexo工具的安装使用,这个工具是依赖于nodejs的一个命令行工具,并且各种使用也依赖于node生态,所以需要先进行nod ...

  9. Kylin-Server-V10-SP3物理机安装简要过程

    1.下载镜像 链接: https://eco.kylinos.cn/partners/mirror.html?class_id=1&query_key=V10 选择: 银河麒麟高级服务器操作系 ...

  10. app自动化设计

    一.在pom.xml引入依赖 testng:测试框架用例管理 appium:需要用到appium log4j:日志集成 allure:生成报告 二.po分层 分为基础层,page层,用例层,xml文件 ...