接下来我想聊一聊,在开发微信公众号阅读器的过程中,我涉及到的一些技术点,以及整体的架构设计。
在项目一开始,我先确定了几个大的技术方向:
首先,这是一个 TypeScript 的全栈 React 应用,并且支持 SSR(服务端渲染)。
其次,在安全性方面,我希望系统具备基本的抗攻击能力,比如认证机制要健全、数据存储要可靠。因此在这一层,我直接选择了一套现成方案——Directus CMS,来负责用户、权限以及数据管理。
在开发框架上,我选择了自己最熟悉、同时也足够简单的 React Router。
UI 方面则比较直接,使用了 Tailwind CSS + Shadcn,这套组合在开发效率和可控性上都很合适。
React Router 本身具备编写服务端 API 的能力(Resource Route),因此在这个项目里,我相当于是直接拥有了一层 BFF(Backend For Frontend)。
这带来的一个好处是:
很多原本需要放在 Directus Flow 或 Extension 里的服务端逻辑,现在可以直接写在应用侧完成。
这样做明显提升了开发体验,同时也让整体的迭代速度更快。
整个项目被我拆分成了三个服务:
Genesis 是整个系统的核心模块,主要负责:
可以理解为用户直接接触到的“主站”。
之所以单独拆出 Nova,是因为有一些能力不太适合直接放在主应用里,比如:
这些功能本质上更偏“中间层”。
另外一个更现实的原因是:
整个项目部署在 Cloudflare Workers 上,而单个 Worker 有 CPU 10ms 的限制。
为了避免单个 Worker 负载过重,我必须把一部分逻辑拆分到另一个 Worker 中去执行。
Nova 就承担了这个角色。
Impulse 是一个相对独立的模块,本质上是一个 cron job 服务,主要负责:
它不直接参与用户请求,而是在后台“默默工作”。
在数据存储方面,我目前没有使用像 Supabase(Postgres)或者 Cloudflare D1 这样的方案。
原因有两个:
相比之下,我选择直接使用 Directus 管理的数据库。
Directus 被我部署在一台国内的云主机上,一年大概一百多块钱。
这种方式的好处是:
Directus 在文件管理这一块的体验非常好:
这意味着:资源访问天然具备权限控制,可以有效防止盗链
由于 Genesis / Nova 部署在 Cloudflare,而 Directus 在国内机房,两者之间存在一定的物理距离。
为了解决这个问题,我做了两件事:
因此:Directus 的域名是不会被直接暴露的
整体来看,目前的架构是这样的:
三者各自职责清晰,同时又保持了比较好的解耦。
这就是目前这个项目的整体技术实现方式。