Folo 源码拆解
以 Folo-dev 源码快照为对象,拆开一个“统一信息流”产品如何通过 Monorepo 同时服务 Web、桌面、移动端、CLI 与 OTA 发布。
这份笔记不是 API 使用手册,而是一条从产品问题走到代码边界的阅读路线。每一章都回答四个问题:
- 它解决了什么问题?
- 源码入口在哪里?
- 数据和控制流怎样穿过模块?
- 这个设计为什么值得保留,代价又是什么?
先看结论
Folo 的核心不是某一个 RSS 解析器,而是一套“远端事实 + 本地投影 + 跨端壳层”的系统:
其中最值得学习的三条主线是:
- 边界复用:业务模型、数据库、Store 和 UI 组件被拆成可复用包,平台差异停留在壳层。
- 本地优先:列表、订阅、未读和条目先进入本地 Store,UI 不直接依赖一次网络请求的生命周期。
- 发布即产品:Electron 安装包、移动端 OTA、Web/SSR、签名与制品证明都在同一个工程里被建模。
建议阅读顺序
第一遍:建立地图
阅读 01 → 02 → 03,先理解 Folo 是什么、代码按什么方向依赖,以及一次启动会经过哪些运行时。
第二遍:追一条数据
阅读 04 → 05 → 06。选择一个 entry 或一次“标记已读”,从 API DTO 追到数据库、Store、React 查询和 SSR 页面。
第三遍:看平台差异
阅读 07 → 08 → 09,比较 Electron、React Native、Web 三个壳层如何共用同一组业务能力。
第四遍:看生产化
阅读 10 → 11 → 12 → 13,理解 AI、认证、权限、版本、OTA、CI 和工程取舍。
研究口径
本文以工作区 Folo-dev 的源码快照为准,版本线索包括 apps/desktop/package.json 中的桌面版本、根目录 pnpm-workspace.yaml 中的 catalog,以及各包的实际依赖。源码会持续变化,因此文中的路径和流程是面向该快照的架构记录,不是对上游未来版本的承诺。
读源码的三个技巧
1. 先读 package.json,再读目录
Folo 的目录很多,但 package.json 才是边界声明:谁是应用、谁是共享包、谁只在开发期存在、谁依赖谁,都能从 workspace 包名和依赖方向看出来。
2. 先找“类型翻译点”
跨边界的数据通常会在这些位置翻译:
@follow-app/client-sdk类型 →packages/internal/*/types.ts的本地模型;- API 返回值 →
packages/internal/store/src/morph/api.ts; - SQLite 行 → Drizzle schema 推导出的 Model;
- SSR hydration 数据 →
apps/ssr/client的 Query/Provider; - 桌面主进程能力 →
apps/desktop/layer/main/preload/index.ts的安全桥。
3. 不把“看起来像服务”的代码当成服务
apps/ssr 既承担 HTTP 服务器,也承担 React Web 客户端;apps/desktop 既是 Electron 打包工程,也容纳 Web Renderer;packages/internal/store 既有 Zustand 状态,也有网络同步和数据库水合。读者需要根据运行时而不是目录名来切分它们。