日序小程序复盘——一个「本地优先」微信日程小程序的架构取舍

仓库:ydflow/rixu-miniprogram-open · 微信原生 TypeScript
一句话:面向普通用户的本地优先微信日程管理小程序。

项目截图

一、背景:日程管理,为什么选「本地优先」

日程管理是个「红海」,但有一个被忽视的真实需求:很多人只想要一个干净、快、不依赖云的记录工具。

「日序」的定位是:记录、安排日期、提醒、专注,再完成。核心设计是本地优先——个人数据先写进微信 Storage,按需同步,而不是强依赖云端。

二、架构:让「本地」和「云端」各司其职

1
2
3
4
5
页面 / 组件
→ Service / Repository
→ 领域规则(日期、重复、提醒、同步、专注)
→ LocalDataStore → 微信 Storage
→ 可选 Cloud Adapter → rixuApi 云函数 → CloudBase

几个关键设计:

1. 页面不直接读写 Storage 或 CloudBase

所有数据访问都经过 Service / Repository / 领域规则层。这带来两个好处:业务逻辑可测试,以及存储层可以替换(本地 ↔ 云端)。

2. 共享数据永远由云函数判断身份

个人数据先本地写入再同步;但共享数据始终由云函数从可信 OPENID 判断身份、权限和版本,前端不拥有写入授权。这是权限边界的关键——客户端永远不可信。

3. expectedVersion 乐观并发控制

共享清单用乐观并发控制处理多端同步冲突,配合 CloudBase 同步,避免「后写覆盖先写」的经典问题。

三、质量:201 个自动化测试 + 结构安全

这是「日序」让我最踏实的部分。pnpm check 执行 TypeScript、ESLint、Prettier、结构安全检查,以及 201 个 Node 自动测试,覆盖:

  • 本地数据、重复规则、同步合并;
  • 共享权限、内容审核失败关闭;
  • 页面静态契约。

我特别看重「内容审核失败关闭」这个测试点——共同专注这种带社交属性的功能,服务端内容安全校验失败时,系统要能安全地关闭而不是崩溃。这是容易被忽略、但上线后可能致命的边界。

四、诚实的边界

「日序」在 README 里把自己「还没做到」的部分写得非常清楚:

  • 尚未发布为正式产品;
  • CloudBase、多账号共享、订阅消息、真机交互仍需自行配置验收;
  • 未实现管理后台、正式订阅消息、生产部署、真实多设备收敛、双账号共享、iOS/Android 真机全量验收;
  • 项目不含 AI、外部日历同步、附件、付费、公开动态社区。

不含 AppSecret、访问令牌、管理密钥、真实环境 ID 或用户数据——project.config.json 用的是微信开发者工具的 touristappid 占位符。这既是安全,也是「诚实地告诉你这不是一个已经跑起来的产品」。

五、几点复盘

  1. 本地优先是「简单可靠」的一种路径。日程这种高频、低延迟需求,本地优先的体验远超「每次操作都转圈等云端」。
  2. 客户端永远不可信。共享数据的写权限只在云函数,用 OPENID 判断身份,这是小程序安全的基本功。
  3. 测试要覆盖「失败路径」。内容审核失败关闭、同步冲突合并,这些边界不测,上线就是隐患。
  4. 诚实标注「未发布」「未验收」,比假装上线更专业,也让项目保持「随时可继续」的健康状态。

「日序」是一个「工程洁癖」型的项目——没有炫技,但架构、权限、测试、边界每一条都扎实。下一篇讲 Pi Native CRM,是这 7 个项目里最「重」的一个:Agent 直接读写真实业务数据。