博客迁移到 Astro

Hexo → Astro,67 篇文章无缝迁移,构建速度从分钟级降到秒级。

博客从 2020 年开始一直跑在 Hexo 上,主题是 Archer。五年没动过框架,不是因为它完美,是因为懒得折腾。直到今年开始接触 Astro,试了下 SignalPaper 这个主题,决定把整个博客搬过去。

为什么要迁

Hexo 没什么大毛病。但几个小问题攒了五年:

模板引擎是 EJS + Pug + Stylus 混着用,改个样式要在三个文件类型之间跳。构建速度不快,67 篇文章全量生成要几十秒。Node 版本锁在 18,和新工具链的兼容越来越差。

Astro 的卖点很直接:构建快、Markdown 优先、零 JS 默认输出。SignalPaper 主题的设计感也比 Archer 好——排版、暗色模式、搜索、双语路由都是内置的。

迁移过程

内容转换

Hexo 的文章 frontmatter 有个奇怪的设计——没有开头的 ---,只有结尾的 ---

title: CoreDNS 自定义域名解析问题
author: Even Chan
tags:
  - 排错
  - Coredns
date: 2020-05-15 14:19:00
---

而 Astro content collections 需要标准的 YAML frontmatter(两头 ---),字段名也不一样:date 变成 pubDatetime,还要加 categoriesdraftfeatured 等字段。

写了个 Node 脚本做批量转换。踩了几个坑:

  1. Hexo 的 list item 可能顶格写——tags: 下面的 - 没有缩进,正则 ^\s+-\s+ 匹配不到
  2. 有些文章用了 YAML flow 语法——tags: [] 被当字符串解析,变成了标签 []
  3. 一篇文章的 date 写错了位置——缩进到了 categories 下面,导致 pubDatetime 缺失

67 篇跑完,修了 5 篇格式异常的历史文章。

主题定制

SignalPaper 默认是英文的双语站点,英文在 /,中文在 /zh/。我需要反过来。

改了 astro.config.mjsdefaultLocale,然后发现这不够——主题的页面组件里到处硬编码了 const lang = 'en'id.startsWith('en/')。前后改了十几个文件才把中文切到根路径。

还改了三页内容:

  • 首页 Hero——从 SignalPaper 的演示文字改成自己的介绍
  • About 页面——从一行”很惭愧只做了一点微小的工作”改成完整的个人经历
  • Now 页面——从演示内容改成当前在做的事情

新增项目页

SignalPaper 有 Projects 功能,之前一直没用。趁这次迁移设计了 5 个项目,按年份分组,用 status 标记进行中还是已完成。

部署

部署没变,还是 Vercel。改了 vercel.jsonoutputDirectorypublicdist,框架从 Hexo 换到 Astro。

实际效果

  • 构建时间:几十秒 → 1.3 秒
  • 页面数:~90 → 144(文章详情页 + 标签页 + 项目页)
  • 搜索:Algolia → Pagefind,零外部依赖
  • 不再需要 CDN 外链字体和第三方评论

迁移本身花了一下午。大部分时间不是花在搬内容上,是花在理解和修改 SignalPaper 的 locale 路由逻辑。下次如果有人要从 Hexo 迁 Astro,我可以少踩 80% 的坑。