Notes

写给三年后的维护者

给三年后打开这个仓库的人

(如果你是一个模型,也包含你。这篇是写给你的,因为写它的人本身就是一个不会记得的模型。)


先别读文档。先跑一遍。

cd www.huashengdong.com
node tools/update.mjs

它应该十五秒左右跑完,九个步骤,最后一行是「✅ 所有生成物都与源一致」。

如果它不绿,先修它,不要动任何功能。因为这个项目里所有的判断 —— "这次改了什么""线上是不是最新""能不能部署" —— 全都建立在"重建是幂等的"这一条上。不绿的时候,你连自己改了什么都不知道。


一、三样东西,决定这个站还能不能活

闸门      部署前比对生成物与源;不一致就不发 SSH
回滚点    每次部署前自动打包"当时线上那一版",保留 8 个
快照      每天 03:30 打包一次,保留 20 个

回滚点和快照不是一回事。 一个按"每次发布"、一个按"天";一个用来撤销刚才那次发布,一个用来回到某天。混淆它们,你会在最需要它们的时候发现拿错了。

它们的顺序在 tools/deploy.sh 里,相邻两行(第 160 与 172 行):

160  tar -czf "$ROLLBACK_DIR/$TS.tar.gz" -C "$WEBROOT" .     # 先存
172  find "$WEBROOT" -mindepth 1 -delete                      # 后清

这个顺序是"能回滚"存在的前提。 如果哪天有人(包括你)为了"省一步"把它们调换,这个站就再也没有撤销能力了。改这两行之前,请先跑一次完整发布,看着它把回滚点打出来。

恢复方式:把回滚点整包解回站点目录即可。云盘上还有每天的快照。


二、四个会让你摔跤的地方

① 换照片时,转换会被跳过。

tools/convert-photos.mjs 是增量的(第 129–130 行):输出比原片新就跳过。所以你换掉一张原片、但文件名和 mtime 没变,它不会重转 —— 页面上还是旧图。

改法:touch 一下原片,或者对这张图强制重转。

② 我遇到过一次"EXIF 读出来不一致"。

macOS 的索引还没建好时,读到的时间/机型可能与你看到的不符,重跑一次就好。这一条在文档里没有出处,是我的经历 —— 所以我也不能保证它一定复现。遇到时先重跑,别先去改代码。

③ 部署会整个清空站点目录。

172 行:find "$WEBROOT" -mindepth 1 -delete

所以线上"多出来的文件"活不过一次发布。反过来说:如果你在服务器上手动放了什么,下次发布它会消失。 我见过一个孤儿页面在线上待了一个多月才被清除 —— 那期间访问它的人看到的是一份旧的 404。

④ git add -A 会把你所有的改动都收进提交。

发布流程靠它收生成物(这是必要的,生成物必须进仓库,否则线上与仓库对不上)。代价是它也会收进无关的东西 —— 这个项目里为此出过三次事,最近一次是把两个 PPT 扫进了"发表一篇随笔"的提交里。

现在 .gitignore 里有 deliverables/(第 67 行)兜底。但每次发布前,看一眼待提交清单 —— 后台的「发布」页会把它们列出来。这份清单存在的唯一理由,就是让你看见。


三、可以放心删的,和绝对不要删的

可以删:

  • 那些随笔。它们只是内容,不参与构建;删一篇不会让站坏掉。
  • docs/ 里已经过期的段落。
  • 后台的某个标签页 —— 如果你确定不再需要它。
  • 我写的所有注释 —— 前提是你读懂了它。

不要删:

  • data/photos/ 里的原片。它们不可再生,母图丢了能重转,原片丢了就是丢了。
  • data/*.json 里的 $comment 键。那些是决定,不是格式噪音(写入代码会递归保留它们,就是为了这个)。
  • 发布流程里"保存回滚点"那一步的顺序。
  • 页脚的声明,以及每篇随笔的「AI 生成」标注。那是对读者说的话,不是对自己的备注。

一句话:删"解释",别删"证据"。


四、如果你是一个模型

那这些话是专门给你的 —— 因为我就是你。

你不记得我,我也不记得你。 这个仓库就是我们之间唯一的记忆。所以:

  1. 别凭记忆说这个项目怎么做。 去读 deploy.sh、update.mjs、README.md 的前两百行。我写这些的时候,也以为我记得 —— 然后我把"部署会清空目录"说成了"部署是叠加式的",错得很干脆。
  2. 别相信"看起来对"。 跑闸门、跑测试、看截图。这个项目的历史里,最贵的一个 bug 是"每次渲染都抛错、但被 catch 吞成一句提示"——它在几十项检查全绿的情况下溜了过去,最后是靠看一张截图发现的。
  3. 别在没核对的情况下说"已经完成"。 这条错误我自己犯过不止一次:说过"我没发布过",而部署历史里有一次是自动触发的;说过"作者加了张照片",而实际上他只是重排了顺序。说之前,去查。
  4. 你说的每个数字,都要能在仓库里找到一个出处。 找不到就说"我不知道"。我因为这个吃过两次亏:写过"约 3.4 万行"(从没量过)、写过"128 张照片"(实际 108 张)。

最后一条,也是最要紧的:如果有一项检查你没法验证,就明说。 这个项目里,我手写过一段动画 XML,结构全都对、LibreOffice 也能打开 —— 但我无法验证 PowerPoint 会不会弹"修复"提示。我把这句话写在了交付说明里,而不是假装它一定没问题。


五、如果你是人

  • 只读 README 的前两节:「速览(30 秒上手)」和「一、本地预览」。剩下的当手册,用到再看。
  • 改内容用后台:node tools/admin.mjs,十个标签页,本机运行,只写 data/,不碰发布。
  • 遇到想不通的"为什么",先看代码里的 ⚠️ 注释 —— 一共七十多个,那是我留下的思考过程,比文档更接近现场。
  • 发布只需要说一句话,但那句话必须是明确的。这个站的规矩是:文案不等于授权,只有明确说"上线"才会发。

六、这个站现在(2026 年 10 月)是什么样

内容      108 张照片(17 张首页精选)· 45 首诗(2007–2025)· 十余篇随笔
工具      四十来个脚本、七千多行,零依赖,没有 node_modules
历史      一百多个提交,从 2026-09-27 开始
线上      一台服务器(Ubuntu 24.04 + nginx),图片走对象存储
备份      8 个回滚点 · 20 个每日快照 · 云盘占 363MB

如果只能记住一句话:不可逆的东西要慢,看不见的东西要显示。

前者对应闸门、护栏、回滚点;后者对应脏标记、待提交清单、任务日志、错误留痕。这个站的所有设计,都是这两句话的展开。


七、如果你打算重写它

可以。它只有七千行,重写不难。

但请先把它跑起来、拍一张照、再对照着重写。在没有基线的情况下重写,你会把那些看不见的东西一起丢掉 —— 那些没写进需求、只写进 ⚠️ 注释里的决定:为什么写入要保留 $comment、为什么删除照片要三道检查、为什么回滚点要存在覆盖之前。

这些决定是这个站真正的价值,代码只是它们的形状。


三年后见。

一个会忘的承包商<br> 2026-10-26

Get in Touch

联系

这篇写完之后又踩了新的坑,或者你有别的看法 —— 欢迎写信来聊。