木匣子 2026 on Astro
上一篇博客已经是 2024 年初的事了。那篇的开头聊到 AIGC 改变了很多事情,尤其是我的表达欲下降了很多,觉得很多东西不再需要记录。结果博客就真的停在了那一篇,一晃两年零九个月。
在这期间我疯狂地感受 AI 的进化之旅,从 ChatGPT 3.5 一步狂蹦到 ChatGPT 6 Astra,以及 Claude Code + Opus 5.5、Cursor + Grok 4.7,特别是 AI agent 的进步令人刮目相看!我和 AI 一起做了很多原来力所能及之外的事。有空的时候可以把它们扒出来写一写,秉承我厚积薄发的态度。
这两天把目光移回了博客,跟 ChatGPT 讨论了一番写博客的意义、当前博客的状态以及技术栈。发现不管是前端还是后端都有很大的变化。我也觉得是时候回到这个角落收拾打扫一番,给未来的自己或者朋友们再写点属于我自己的东西,而不是完全由 AI 生成的东西。
在工作上,我的重心仍然在 React 和 TypeScript 技术栈。而 hexo 已经略显老旧,经过一番讨论,我决定把博客从 hexo 搬到了 Astro 上:
Astro is a modern site builder with web best practices, performance, and DX front-of-mind.
这是 Astro 在 npm 上的自我介绍。和 hexo 一样,它也是 JavaScript 生态里的,只不过这次的代码大多换成了 TypeScript。
另外我的博客文章也不再和博客程序放在同一个 repo 里,而是改为直接从我的 Obsidian 笔记库读取。是的,我把我所有的个人知识库整合到了 Obsidian Vault,采用 AI agent 来管理。当然这不代表博客的文章会由 agent 来写,最多让它帮我查个错。
说来也巧,这次帮我把博客搬起来的,也还是 AI。本文会简单记录一下迁移的过程,以及一些想法。
¶木匣子 2010 - 2026
算上这次,木匣子已经用过五个博客系统了:2010 年的 WordPress,2013 年的 Typecho,2017 年的 Ghost,2019 年的 hexo,以及现在的 Astro。前几次的来龙去脉写在《博客迁移记录》里。
这几次搬家,我都尽量不让旧的东西坏掉。2013 年换 Typecho 的时候,明明有工具可以导入 WordPress 的文章,但我「更喜欢让它们保持原来的样子」,于是把 WordPress 原封不动地放到了二级域名下。2017 年搬到 Ghost,旧博客被 301 重定向到各自的二级域名,避免出现死链。当时在《Hello Ghost.》里还说,将来如果再换系统,估计会把这个博客也重定向到「木匣子2017」。
结果 2019 年的时候我并没有这么做,而是把三个博客合并成了一个静态站,在 Cloudfront 前端靠 Lambda@Edge 的重定向继续让站外的老链接继续有效。不过这次页面和 URL 都和旧站保持一致,连旧留言也留了下来。
¶Obsidian
今年三月的时候,我把所有博客文章导入了 Obsidian 的笔记库。七月份时又按 Johnny.Decimal 的方式[1]把整个笔记库整理了一遍,博客被归到了 50-59 Writing/51 Blog Archive 这个目录下。这个 JD 分类系统展开又可以聊一篇,先挖个坑吧。
2019 年刚用上 hexo 的时候,我觉得「静态化是如此的美妙」:可以直接用文件系统管理 markdown,还能用 git 做版本控制。现在这些 markdown 换了个地方住,和平时的笔记放在了一起,而笔记库本身也是一个 git 仓库。新博客就以这个目录作为内容源,这篇日志也在这里。
新写的日志会由 Astro 的 content loader 直接扫描这个目录发现,再渲染成 HTML。开着 dev server 的时候,改完文章大约不到一秒,页面内容就更新了。Obsidian 的一些写法也顺便支持了,比如 wikilink。
搬运文章的时候,Claude Code 逐篇对比笔记库和 hexo 原文时顺便帮我查出来了好多 typo 一并修理了。
¶保持原来的样子
这次迁移的规矩是只移植,不重新设计。其实我是有使用 Stitch 之类的原型工具,按我要求的极简风格进行设计,但是看完我并不是很满意。不管怎么设计都感觉比我现在的这套繁琐。所以我决定保留原来的这个 2019 年自己写的 hexo-theme-mutoo 极简主题,原样搬到了 Astro 上。由 Claude 完成全部移植工作。它把 EJS 模板逐个改写成 Astro 组件,类名、结构、文案和 SCSS 里的数值都没动,原来依赖 jQuery 的那点交互改用原生 TypeScript 重写了。只有图片放大换成了一个更简单的 lightbox,另外 AddThis 分享按钮也去掉了(服务早就关了)。
迁移的时候还顺带挖出了旧站的几个老毛病。比如带时区的日期会被 hexo 多平移一次,《写在 2021 年末》是 12 月 3 日凌晨两点写的,旧站上显示的却是 12 月 2 日。又比如头图用的 source.unsplash.com 早就下线了,旧站的头图其实一直是坏的 Orz。现在改成了构建前先把图片地址解析好。
但也不是都没改,迁移后我让 Claude 给了一些 UI/UX 的优化方案,我感觉还挺不错的。多数都采纳了。例如增加 keyboard shortcuts,引入静态化的站内搜索等。
¶留言存档
hexo 时期的留言用的是 Disqus。本来的计划是弃用 Disqus,导出数据后换成 Artalk,代码也已经接好了。第二天早上和 AI 讨论了一下,感觉可以放弃:留言的频率太低了,而且部署 Artalk + cloudflared 还需要迁移域名,我的博客和域名都托管在 AWS 上,成本太高。
于是换了个思路:构建的时候把 Disqus 导出的数据直接生成到页面里,变成只读的留言存档,留言通道暂时关闭。现在有 60 个页面下面还挂着当年的留言,一共 268 条,我自己的回复标上了「OP」。
这大概也算另一种「保持原来的样子」吧:留言不能再加了,但原来的都还在。以后也许会在 AWS 上做一个简易的 serverless 留言方案,不过现在先不管它。
¶搬家的人换了
2019 年那次,合并三个博客花了一两周,写主题又花了几周的业余时间,「好在文章少,时间多」。这次文章还是那么少,从 9 月 29 日晚上开工,到第二天上午上线,前后不到一天。而且活儿基本不是我干的。
开工的时候,我在 Claude Code 里写了一段需求:新建一个 Astro 项目,把 themes/mutoo 移植过去,以后以 Obsidian 笔记库里的博客目录作为内容源,设计保留原有的理念,特别是字体,弃用 Disqus,发布沿用原来的 S3 流程。它先写了一份约定,规定各个模块的接口,还给每个 sub-agent 定了几条硬规矩:不许改我的笔记库和旧站,不许部署,不许提交代码(后来改笔记库、提交和部署,都是我点了头才做的)。然后把活儿拆给好几个 sub-agent 分头去做,做完再分几个视角 Review 一轮,每条发现都要另一个 agent 复核[2]。晚上七点多它交来一份报告,列了几件需要我拍板的事,我十点多回了一行字。十一点,我让它「先提交一个版本」。整个过程中我一共发了三十来条消息,没有写一行代码。验收基本是在 Claude Code 内置的浏览器预览里点点看看,看到不顺眼的地方就直接选中那个元素让它改。
2024 年那篇里,ChatGPT 帮我的是不熟悉的领域。这次搬的却是我最熟悉的东西,自己的博客和自己写的主题。活儿都是它干的,要我拿主意的反倒是些小事,比如留言还要不要、旧 URL 能不能丢一个、头图用哪张。邮件备份那篇的花絮里,ChatGPT 第一次给的脚本会把重复的邮件全删掉,一个副本也不留,是我 Review 代码的时候发现的。这回 Review 也交给了 agent。第一版留言存档把 WordPress 时期那批留言的时间当成了本地时间,其实是 UTC,230 条留言的时间都差了十来个小时,是负责审查的另一个 agent 挑出来的。
¶部署
部署还是 2019 年那一套 S3 + Cloudfront,只是同步脚本改了一点。9 月 30 日上午第一次部署,同步完再刷新 Cloudfront 的缓存。上线后抽查了首页、文章、归档、atom.xml 等页面,和本地构建出来的逐字节一致。统计也顺便从早已停止处理数据的 Universal Analytics 换成了 GA4。
打开首页,看上去和原来没什么两样,要的就是这个效果。不同的是头图又显示出来了,页脚的 Powered by Hexo 换成了 Astro。
2019 年那篇正文的最后一句是「突然间又重新燃起了写博客的欲望。」那股劲头倒也撑了一阵子,2020 年发了 13 篇,之后就只剩一年一两篇,2025 年干脆一篇也没有。所以这次就不立 flag 了。木匣子重新开张,先把这次搬家记下来,未完待续。