为什么我要从零手写一个博客,而不是直接用现成的
用 Hexo 五分钟就能搭好一个博客,我却花时间自己写了一个。这篇讲讲这个决定背后的取舍,以及这套代码是怎么组织的。
起因
毕业一个月,我买了台阿里云的轻量应用服务器。买的时候想着「以后总用得上」,结果它空转了两周。
同时我意识到一个更麻烦的问题:我写的代码,大部分是 AI 生成的。 能跑,能交付,但如果你现在问我「这段为什么要这么写」,我多半答不上来。
这两件事凑在一起,答案就很清楚了:做一个必须自己理解才能维护下去的项目,然后把过程写出来。
为什么不用现成的
Hexo、Hugo、WordPress,五分钟就能有一个比这个好看的博客。我认真考虑过。
但现成方案有个问题:它把所有值得学的东西都藏起来了。
- 文章怎么从 Markdown 变成网页?—— 主题引擎处理了
- 数据存在哪、怎么查?—— 框架处理了
- 服务器上怎么跑起来的?—— 一行
deploy命令处理了
对想快速开始写作的人,这是优点。对想搞懂这些的人,这是屏障。
所以我选了折中方案:自己写,但只写必要的部分。
这套东西是怎么搭的
核心决定:文章不进数据库
最关键的一个设计:
文章的真身是
content/posts/下的.md文件,用 Git 管理。 数据库只是这些文件的索引 + 缓存 + 计数器。
content/posts/notes/xxx.md ← 真身,Git 管着
↓ 启动时扫描、渲染
MySQL posts 表 ← 索引、标签、浏览量
↓ 查询
网页
这样做的好处:
- 数据库删了也不丢文章,重新同步一次就回来了
- 改文章 = 改文本文件 +
git commit,天然有完整的修改历史 - 不需要登录后台,也就不存在密码被爆破、后台被入侵这类问题
最后一条对我这种新手特别重要。一个带登录的后台,意味着我要自己处理密码哈希、会话管理、防暴力破解、文件上传校验……任何一环没做好都是漏洞。而我现在的水平,做不好。
能力不够的时候,不要给自己造那么多需要守的门。
目录结构
blog/
├── app/ # 后端代码
│ ├── config.py # 配置(全部从环境变量读)
│ ├── database.py # 数据库连接
│ ├── models.py # 数据表定义
│ ├── markdown_render.py# Markdown → HTML
│ ├── sync.py # 扫描 .md 文件同步进库
│ ├── services/ # 数据库查询
│ └── routers/ # URL 路由
├── content/posts/ # 文章(.md)
├── templates/ # 页面模板
├── static/ # CSS / JS
└── deploy/ # 部署脚本
一条规矩:每个文件只干一件事。路由函数不写 SQL,SQL 不写在模板里。文件多一点没关系,找东西的时候会感谢自己。
增量同步
每次启动都把所有文章重新渲染一遍是很蠢的。所以同步的时候会先算文件的 SHA256:
digest = hashlib.sha256(raw_bytes).hexdigest()
# 数据库里已有这篇、并且 hash 一样 → 文件没改过,直接跳过
if existing is not None and existing.source_hash == digest and not force:
return slug
这是我第一次真正理解「哈希用来判断内容有没有变」这件事——以前只在面试题里见过。
一个差点踩的坑
更新文章时不能整行覆盖,因为 views(浏览量)只存在数据库里,源文件里没有。
一不小心写成「删掉再插入」,每次改错别字都会把阅读量清零。
学到了什么
写完这一版,回头看学到的东西比预想的多:
| 想学的 | 实际用在哪 |
|---|---|
| Python | 整个后端,第一次写超过 10 个文件的项目 |
| MySQL | 建表、索引、多对多关系、views = views + 1 的并发问题 |
| Linux | 服务器部署、systemd、日志、权限 |
| Git | 每篇文章一次 commit |
| Nginx | 反向代理、静态文件、以后上 HTTPS |
而且这些不是看教程学的,是为了让自己的网站跑起来才学的。动机完全不一样。
接下来
这个博客会一直改。我打算把每次改动都写成一篇笔记:加评论、上 HTTPS、把 LIKE 搜索换成 MySQL 全文索引、加访问统计……
如果你也是刚入行、也觉得「AI 写的代码看不懂」很焦虑——我的建议是:找一个你真的想要的东西,然后自己做出来。 不用做得多好,能跑就行。理解会在维护它的过程里慢慢长出来。
这篇是第一篇。往后见。