Aug 11, 2021 / Blog / Comment System

博客重构:2021 / 第二章

💩➕➕

去年暑假学习用 Node.js 糊了本站的评论系统,后端使用了 Express + MongoDB (Mongoose),前端则是手动操作 DOM 来渲染。一开始感觉还不错,跑也能跑,但写的实在是太乱了。今年暑假想再改一改都无从下手。

前端部分需要自己手动操作并更新 DOM 数据,也没有搞 MVC 架构,全部都糊在一起写。最要命的是样式没有和主题拆分开来,导致如果我换主题,评论的样式就会完全乱掉。两个不同的项目,本就不应该有这么高的耦合。

去年写的那篇关于评论系统的文章已经被我隐藏了,带有很多错误的决策,修完一些大学科目后才明白。
对后端没有什么经验,这篇文章同样可能有很多错误,欢迎指出。

语言 & 框架

Nest.js

去年选择用 Node.js 写后端是因为只写过这个语言(虽然在学校有接触过一点 C++)。所以一开始打算再用同样的语言重构一遍,用上 Nest.js 这个框架 + TypeScript + MongoDB。选择 Nest.js 只是为了学习一个 Node 后端框架,看它比较流行。但试着写了几天后感觉并不是非常好,一个简单的评论系统似乎没必要用上这么大的框架,自己反而被很多新的概念给限制住了。

有个我不太喜欢的地方,其实也不算是框架的问题,应该是因为 JS 没有真正的类型系统,再加上 TypeScript 是鸭子类型,所以有些类型转换虽然可以过得了检查 & 编译,但是后端序列化后就会出现多余的属性。

例如说有一个 A 和 B 类型:

class A {
    prop1;
    prop2;
    prop3;
}

class B {
    prop3;
}

A 是可以转换成 B 的,但是如果直接 JSON 序列化后返回,就会发现多了 prop1 和 prop2。想要解决这个问题可以通过添加一个 ClassSerializerInterceptor 拦截器,借助 class-transformer 这个库的功能来标注哪些字段应该被转换成 JSON。

虽然最后没有继续使用 Nest.js,但学到了拆分 DTO,Model 和 Entity。(软件工程上有学到这些内容,但完全没实践过 🥲)

Golang

这个暑假其实还想学习下 Golang,所以就钦定你了

Web 框架用的是 Echo。一开始是想试试看 Gin 的,但感觉它的文档好像没 Echo 的好,所以就选前者了。后来发现 Go 的 Web 框架都是基于 STD 的封装,用起来大部分都差不多。

数据库这次决定改成用 SQLite。因为评论本来就没有几条 😭。主要是为了换 VPS 的时候不用装环境,一个文件扔上去就能跑了。也可以学习下关系型数据库的使用和管理。

ORM 用了 Facebook 的 ent,和隔壁 Node 的 Prisma 有点像:先描述数据库的结构,然后静态生成数据库 API。我感觉用起来很舒服(可能是我用的都是很基础的数据库功能)。

去年使用了 Telegram Bot 来搞新评论提醒和管理,后来踩了几个坑:

  • 只过滤掉评论的 HTML 标签还不够,有些特殊字符还需要进行转义
  • 信息有长度限制 (不清楚具体是多少,但很长的评论直接塞进去会报错)

今年本想学习如何搭建一个后台系统来管理评论,最后感觉还是太麻烦了,直接 Telegram 提醒解决。为了避免上面两个坑,不再插入评论内容,而是提供一个按钮跳转到评论页面。

资源占用看起来比去年的版本少了很多。记得当时的 RAM 使用在 60 ~ 100 MB,这次的版本能稳定在 20MB 左右,应该有语言加成。速度也快了不少。

前端

这次选用了 Vite + Svelte + WindiCSS 来写前端,把主题和评论拆分开来,方便换主题。不用自己手动更新 DOM 的确舒服了许多,少了很多工作。

Vite 支持把项目编译成库,可以参考官方文档:Library Mode。默认编译成 ES Module,可以直接在现代浏览器内通过 <script type="module"> 加载,很方便。

使用 WindiCSS 而不是官方的 TailwindCSS 是因为前者速度真的快了好多。后来后者也推出了 JIT 模式,不知道现在速度怎么样。我个人还是推荐用 Windi 的,兼容 Tailwind,还有更多功能。

最后

我本以为这次重构后后端的代码会好很多,但还是不堪入目。尤其是昨晚看了别人的 Golang 项目后更感觉自己写的是一坨 💩 ,难受了好久。所以也没打算把这篇博文写的非常详细,自己的做法或许并不是对的。

希望有一天能写出让自己满意的代码吧。

CC BY-NC-SA 4.0