Web 玩具项目技术栈

我曾经是 Pinboard 的用户,用了几年后涨价,觉得不是很值那个钱,于是决定自己写个服务替代它。这个书签服务定位为私人工具,功能基础,无社交功能。桌面端支持 Chrome 浏览器,移动端通过 Telegram bot 创建书签。
技术选型
这个服务可以说非常简单,一个数据库,一些 CRUD 接口,以及一个页面。任何语言和框架都能从零到一写出来。我的选择是后端 Go,前端 Vue,数据库 PostgreSQL,部署在 DigitalOcean 的 Kubernetes 上。

这么做有几个原因:
- 首先 Go 是当前我写的最多的语言,无需学习成本。此外,性能好,非常适合写在线服务。
- 选择 Vue 是因为看到一个 UI 库Naive UI,有设计品味,想尝鲜。
- 数据库使用 PostgreSQL 是因为开源社区的推崇,功能和插件都很丰富。
- 部署选择 DigitalOcean Kubernetes主要是性价比高,大厂的 Kubernetes 价格都贵很多。用 Kubernetes 主要是想深入学习理解云原生实践。
- 域名托管在 Cloudflare 上,开启 argo 路由优化。
业余时间大概搞了一个多月,写了一版出来,给身边的朋友尝鲜,效果还可以。不过我也发现了些问题,最大的问题是从有限的业余时间和成本上看不理想,像这类 Web 项目后端主要是 CRUD 接口,复杂的业务逻辑几乎没有。既然是玩具项目,委托给工具或服务自动生成 API是比较好的选择,避免自己再手写一遍。部署在 Kubernetes 上也是没必要,用 PaaS 平台便宜且方便。整套下来,在 DO 上每月开销 $60,后来经历了涨价,开销到了 $80。于是决定改变技术栈,从时间和开发成本角度重新选择工具。
重新选择
恰巧工作上接触到一个项目使用了 GraphQL,第一印象很好。于是调研了开源社区,Hasura 是个不错的选择,但优缺点挺明显,优点是作为代理层开箱即用,CRUD 语句会转成 SQL 直接查询 PG 数据库,业务方不用再单独存储数据。缺点是权限管理复杂,需要业务方提供鉴权接口,复杂的业务逻辑交互上比较麻烦。还有个现实的问题是,一些场景没法用 GraphQL 替代掉,RESTful 接口不可替代。新技术总是在某些场景比旧技术好,但是也会带来新的问题,所以辩证看待就好。总的来说,我愿意在一些不重要的场景渐近式引入新技术,比如后台场景里自己用 GraphQL 查询,而不是暴露给用户使用。

后来研究了一些热门开源项目技术栈,最终确定为 Next.js 和 Supabase 的组合,服务部署在 Fly 上。这次挑选原则是薅资本主义羊毛,能拿则拿,能省则省,能快则快。稳定性不再是首要因素。

理由如下:
- Vue 和 Go 换成了 Next.js,是因为 React 的生态完善太多,想要啥功能几乎都有现成的库,不用自己重新写。目前在用 Mantine 和 Radix UI 两个库,是那种我愿意每个月捐助的项目。
- Supabase 自诩 Firebase alternative,不仅提供 PostgreSQL(支持选择地区部署),还提供了数据库 CRUD API(利用 PostgREST)、Auth UI、文件存储、Edge function 等功能,免费额度足够玩具项目开销。
- DigitalOcean 涨价后价格有点高,换成 Fly 薅免费的额度,部署地区也多了许多,目前部署在 HK 地区,从国内访问会快些。
改成这套技术栈之后,重写了书签服务,开发效率有几倍的提升。粗算了下,时间主要花费在组装前端页面上,读接口直接走 Supabase API,写接口会涉及到事务操作,因为 Supabase API 不提供事务操作(我认为最大的槽点),需要通过 Next.js API 和 Prisma 封装一下。这套组合下来,部署成本从 $80 到 0,虽然这么比较不是很公平,但钱是省下来了😂
目前的服务效果图如下,还在优化中,暂不对外开放,感兴趣可以私聊。

总的来说,Next.js + Supabase + Fly 是一套不错的组合,适合玩具项目起步,稳定性方面还需要进一步验证。