借助AI将博客从Jekyll迁移至Hugo
将博客从Jekyll迁到Hugo,是我几年前就想做的事了,然而积重难返,力有不逮,这几年也就逐渐淡忘了。为什么想要抛弃Jekyll呢,喜新厌旧的心态远胜于实际需要,Jekyll所被诟病的性能差的问题,在我的环境中并不关键,构建速度从8s提升到2s,看似有4倍之巨,实则并没有那么大的吸引力,还是对未知事物的探索更诱人。
如今有了AI,又有闲心,便想重启这一工程。我想要的是1:1复刻,AI并不能一步到位进行转化,但90%的工作确实都是由它完成。从一种形态切换到另一种形态,最重要的是观念的转变。Jekyll和Hugo虽然相似,但并非完全对应,当了解Hugo构建网页的逻辑后,很多问题也便迎刃而解了,对不懂编程的我来说,这是一个艰难的过程,也有事先未阅读官方文档的原因。
第一步是模板的迁移,Hugo有自己内置的引用逻辑,不如Jekyll用layout指定那么直观,主页、文章、页面需要用什么模板都得重整,对我来说是整个迁移过程中学习曲线最陡峭的部分了。AI的信息有点落后,它提供的架构是老版本的,而新版本进行了结构和逻辑的优化,不管是ChatGPT还是Gemini似乎都不太了然。幸亏我在迷惑之时想到了官方文档,否则就被AI带入落后版本的境地里了。
第二步在迁移资源文件时遇到了最大问题,是Sass一直编译不成功,和AI“讨论”了一两个小时,尝试了不同编译写法、文件结构和语法检查,最终的怀疑点在Sass的解析器上,看过官方文档后确认如此。因为我用了@use的新语法,需要用Dart Sass解析,而Hugo默认使用LibSass。在编译函数上,ChatGPT用的是已废弃的resources.ToCSS,Gemini却知道用新的toCss,这大概是在此次任务中Gemini唯一胜出的一处。
后面都是一些具体而微的问题,捡一些主要的来说。非常重要的一步是posts的适配,Hugo的语法要求更为严格,而我旧文的front matter无法通过检查。文章有几百篇,当然是让AI帮忙写脚本批量处理,Gemini写的脚本引入了新问题,而ChatGPT的脚本一次性就成功了。想来这一步若无AI而让我自己抠脚本,不知要忙到何时。
Hugo更为严格的一个地方在于不能在markdown中执行模板语言,比如partial等,而我在Jekyll中大量使用了此类写法,所以很多页面要重写。Hugo采用的方法是将其编写为shortcode,再在markdown中引用,相比Jekyll多了一步,也完全可以接受。对于图片的插入,我在Jekyll中使用了include的方法,自然也要转换为shortcode,并让AI对功能进行了扩展,支持插入单张或多张图片,这却只是因为某篇文章在新环境中无法再使用模板语言的循环结构。
有一处让人遗憾的功能是Hugo不支持csv格式的数据集,对我来说这是维护读书列表最简单的方式。Hugo也可以处理csv文件,但AI提供的data.GetCSV方式已废弃,用transform.Unmarshal却遇到了csv文件的BOM问题,怎么也修复不了,只能忍痛将读书列表转成了json格式。
Hugo的链接格式生成也不如Jekyll符合心意。我已养成了2025-12-14-hello-world.md风格的文件命名习惯,觉得如此更为条理,但Hugo的:contentbasename不能像Jekyll一样自动取文件名中的英文标题加入链接,:title又带有中文,唯有在front matter中多加一个 slug字段来指定链接内容。
还有一个无伤大雅的功能便是字数统计,前几天才刚让AI写了能较准确统计中英文混排字数的Jekyll插件,现在却突然改弦易帜了,插件也无用武之地。虽说Hugo也能编码实现相同功能,但我图省事就用内置的{{ .WordCount }},在站点配置hasCJKLanguage = true的情况下也还堪用,不过会虚高一些。
Hugo也是老人了,难怪AI掌握的多是一些过时信息,最新的静态博客引擎是什么,我暂时没有兴趣。Hugo就是我以前心中的“白月光”,如今已达夙愿,也可安稳一段时间——Jekyll不也用了七年吗,难道是七年之痒——即便博客再写好多年,Hugo的性能也足够。我觉得Jekyll和Hugo各有千秋,正如开头所说,此一番折腾不过是喜新厌旧而已。而此次工程的两位帮手,俱是免费版的ChatGPT和Gemini两相比较,我觉得ChatGPT写的代码更简洁、更健壮、也更有效。至于一开始订立的1:1还原目标,实际并未完全做到,不是不能,而是没有必要了。