2019 年 10 月 1 日国庆假期,我把一套 Xiuno BBS 论坛程序改造成个人博客,正式开张。2026 年 10 月 1 日,同样是国庆假期的清晨,我打开了 Claude Code,对它说:把整个博客重构一遍。当天深夜,新站上线。这篇文章记录一次跨越七年、却只花一天的完整重构——为什么拖了这么多年,AI 又是如何把"以月计"的工作压缩进二十四小时的。
1、七年之痒
七年里,这个站积累了不少家底:868 篇文章、约 1571 个帖子、53 条读者评论、1672 个附件共 176 MB,分布在 12 个版块里——Android 169 篇、View 120 篇、分享 103 篇、开源 83 篇、AI 76 篇,一路排到数据库 8 篇。
但底子是老的:Xiuno BBS 4.0.4,PHP + MySQL 的论坛程序,被我用 60 多个插件硬拗成了博客的样子。它带来的问题一年比一年明显:
- 官方早已停止维护,安全补丁只能自己背
- 密码体系还是
md5(明文 + salt)的上古方案 - 富文本编辑器输出的 HTML 依赖 SyntaxHighlighter,代码高亮时灵时不灵
- 移动端排版停留在"能用"的级别
2、为什么迟迟没动
重构这件事,我至少认真想过三次,每次都停在同一堵墙前:
| 障碍 | 具体分量 |
|---|---|
| 精力 | 博客是业余维护,手写一套全栈系统要以月计 |
| 技术栈 | 前端早已换代,从零追起成本太高 |
| 数据包袱 | 868 篇 HTML 正文、3606 处站内旧链接、5308 处图片相对路径、6060 个代码块,老 URL 一个都不能断 |
真正的变化不在技术,而在协作方式。当 AI Agent 能够独立读库、写迁移脚本、起服务、开浏览器自测、跑类型检查并且自己修错时,上面三堵墙同时矮了下去——精力和技术栈被 AI 补齐,数据包袱则变成了 AI 最擅长的批量结构化劳动。
3、一天的重构
2026 年 9 月 30 日晚,从一份 35 MB 的 MySQL dump 开始选型,很快定案:
| 维度 | 旧站 | 新站 |
|---|---|---|
| 框架 | Xiuno BBS 4.0.4(PHP) | Next.js App Router(TypeScript) |
| 数据层 | 裸 SQL | Prisma 7 + MySQL 8 |
| 样式 | 论坛主题 | Tailwind CSS 4,深浅色双主题 |
| 代码高亮 | SyntaxHighlighter | Shiki 双主题预渲染 |
| 密码 | md5 + salt | argon2id,旧密码首登无损升级 |
| 会话 | Cookie | 数据库会话,后台可踢人下线 |
国庆当天的工作节奏大致是:上午数据模型与迁移管线,下午全站功能(前台列表、文章页、搜索、归档、后台管理),晚上打磨细节与安全加固。下面这条命令跑完,868 篇文章全部落进新库:
npm run migrate
# 01-users 02-categories 03-tags 04-posts
# 05-comments 06-likes 07-attachments 08-slides-settings
4、868 篇无损迁移
迁移的核心是一条清洗管线,每篇文章依次过七道工序:按旧格式选源、重写 3606 处站内旧链接、转换 5308 处图片路径、清理空段落与首行缩进、标题层级归一化、Shiki 语法高亮、HTML 白名单消毒。
6060 个代码块全部按真实语言重新高亮——java 4937 个、html 586 个、bash 419 个,最小的 ruby 也有 1 个。全库扫描下来,真正的乱码只有一篇文章里的 2 个字符,而且是老数据库里就坏掉的,不是迁移引入的。
有损与无损的边界也重新划过:773 篇公开发布,95 篇老"私有"与"草稿"统一转为草稿态,对外不可见但一篇没丢;53 条评论全部找回(此前甚至没有迁过);老链接 /?thread-123.htm 全部 301 到新地址。栏目做了合并瘦身——View 与 AOSP 并入 Android 并自动打上同名标签,AI 栏目里 Skill 相关的 9 篇独立成新栏目。
5、编辑器与写作流
七年前的写作规范是为富文本编辑器定的:HTML 装进 txt、首行 缩进、代码块一律标 java。这次重构把写作流整个换成了 Markdown 优先:
{
"dependencies": {
"next": "16.x",
"@prisma/client": "7.x",
"@node-rs/argon2": "^2.2.1",
"shiki": "^3.x",
"marked": "^15.x",
"isomorphic-dompurify": "^2.x"
}
}
新编辑器分屏实时预览、支持 20 种语言的代码块插入、图片视频粘贴即上传、Ctrl+S 保存、本地自动保存兜底。发布管线与迁移同级:AI 生成的 Markdown 直接粘贴,标题层级、老格式残留、代码高亮在保存时自动归一。配套的《博客格式规范 v2》取代了 2019 年那份——以后博客由 AI 按新规范生成,人是审稿人。
6、安全与细节
安全上没有偷懒:登录做了双层防爆破——IP 维度 10 分钟 5 次,账号维度递进锁定,从 5 次锁 10 分钟一路升到 20 次锁 24 小时,换 IP 也绕不过;所有用户输入的 HTML 过白名单消毒,iframe 只放行可信域名;会话落库,改密、封禁即刻生效。
一天里也有不少"AI 才会踩"的坑:比如全站唯一一篇层级错乱的文章,是重构当晚后台编辑保存时管线少了一步归一化,补上后连历史那篇一起修了;再比如图片懒加载让轮播切换瞬间露出白底,改成预加载加深色兜底才干净。
7、上线路演
重构完成只是上半场,把新站部署到跑了六年半的老服务器,是下半场的故事。这台 2019 年陪着博客开张的 CentOS 7,uptime 已经超过 2300 天,但它早已停止维护——glibc 停在 2.17,这个数字成了整个部署之夜的主角。
现代 Node.js 的官方二进制要求 glibc 2.28,MariaDB 也早已不再为 CentOS 7 构建包。于是部署变成了三场硬仗:
- Node.js 20 源码编译:两小时的编译,中途两次被 OOM 杀掉——最吃内存的 V8 编译单元单文件就要 1.5G,而整机只有 1.8G 内存。加 3G swap、单线程续编、深夜短暂停掉老站的 php-fpm 腾内存,才终于看到 BUILD_OK
- MySQL 8 独立实例:官方 el7 源安装,跑在 3307 端口与老库完全隔离;踩了 Windows 表名不区分大小写、MySQL 8 默认认证驱动不认两个经典坑,分别用初始化参数和认证插件解决
- 构建与原生模块:Turbopack 的 standalone 输出给 Prisma 的包名加了哈希后缀导致 500,换 webpack 构建解决;argon2 的 Linux 二进制没被构建带入,手动补装平台包
凌晨,HTTPS 证书签发、Nginx 切换、PM2 守护一气呵成——https://quibbler.cn 挂上了新站,老站的 php-fpm、MySQL 5.6 和一个跑了多年的小服务陆续下线,释放出近 200M 内存。从 2019 年国庆到 2026 年国庆,这台服务器上的两代博客完成交接。
8、七年总结
盘点这次重构:868 篇文章、7 年积攒、1 天重构加一夜部署、AI 全程结对。旧站的每一个数字都有了下落——文章、评论、附件、内链、甚至密码哈希都无损衔接。
七年前搭这个博客用了整个国庆假期;七年后重构它只用了一天。变的不是我的手速,是"一个人拥有体面个人基础设施"的成本被 AI 压到了一个新量级。对于还在守着老系统犹豫的独立站长,我的建议很直接:先把数据 dump 备份好,然后挑一个假期,和 AI Agent 结对把它重构掉——拖了七年的事,真的只需要一天。
