从 Jekyll 迁移到 Hugo……还是不迁移
Source: Dev.to

Source:
背景
我在 WordPress 上开设了这个博客。几年后,我决定迁移到 Jekyll。到目前为止,我对 Jekyll 感到满意。它基于 Ruby,虽然我不是 Ruby 开发者,但我仍然能够编写几个插件。
我把代码库托管在 GitLab,并使用 GitLab CI,同时配置了 Renovate,当 gem 过期时自动创建 PR。这样,我每次都会处理技术债务,而不会让它在多年里累积。上周,我收到一个 PR,想把父 Ruby Docker 镜像从 3.4 更新到 4.0。
我检查了 Jekyll 是否已经兼容 Ruby 4。结果显示它还没有兼容,尽管已经有一个未解决的问题。然而,不仅是 Jekyll:Gemfile 中使用的 gem 版本也与 Ruby 4 不兼容。
更糟的是,我查看了 Jekyll 项目 的整体健康状况。最近的提交都是几周前由持续集成机器人完成的。我想也许是时候寻找替代方案了。
Hugo
就像 Jekyll 一样,Hugo 是一个静态站点生成器。
Hugo 是最受欢迎的开源静态站点生成器之一。凭借其惊人的速度和灵活性,Hugo 让构建网站重新变得有趣。
与 Jekyll 不同,Hugo 基于 Go 构建。它自称“惊人地快”。锦上添花的是,代码库的活跃度远高于 Jekyll。虽然我不是 Go 的粉丝,但我认为 Hugo 是一个很好的迁移目标。
Jekyll → Hugo
从 Jekyll 迁移到 Hugo 遵循帕累托法则。
迁移内容
Hugo 提供以下主要文件夹:
| 文件夹 | 用途 |
|---|---|
content | 需要处理的内容 |
static | 原样复制的资源 |
layouts | 模板 |
data | 数据源 |
请参见完整列表了解全部内容。
Jekyll 将 posts(带有日期)和 pages(不带日期)区分开来。Posts 是博客的基础;pages 稳定且用于构建站点结构。Hugo 并不做此区分。
Jekyll 文件夹到 Hugo 文件夹的映射:
| Jekyll | Hugo |
|---|---|
_posts | content/posts |
_pages/.md | content/posts/.md |
_data | data |
_layouts | layouts |
assets | static |
当映射不足时
Jekyll 提供插件。插件分为以下几类:
- Generators – 在站点上创建额外内容
- Converters – 将一种标记语言转换为另一种格式
- Commands – 为
jekyll可执行文件扩展子命令 - Tags – 创建自定义 Liquid 标签
- Filters – 创建自定义 Liquid 过滤器
- Hooks – 细粒度控制以扩展构建过程
在 Jekyll 中,我使用 generators、tags、filters 和 hooks。有些通过已有的 gem(例如Twitter 插件)使用,其他则是为满足个人需求而自行开发的。
Tags → Shortcodes
Jekyll 的 tags 在 Hugo 中对应为短代码:
短代码是一个 template,在标记中调用,可接受任意数量的 arguments。它们可以在任何内容格式中使用,用于插入视频、图片以及社交媒体嵌入等元素到你的内容中。
短代码有三种类型:嵌入式、定制和内联。Hugo 提供了丰富的内置短代码集合,你也可以自行编写。
Generators → No direct equivalent
不幸的是,generators 在 Hugo 中没有直接对应。我曾开发 generators 用来创建新闻简报和演讲页面。该插件会根据我的数据自动为每一年生成一个页面。而在 Hugo 中,我只能手动为每一年创建一个页面。
迁移 GitLab 构建
Jekyll 构建包括三个步骤:
- 检测
Gemfile.lock、Dockerfile或.gitlab-ci.yml是否有更改,如有需要则重新构建 Docker 镜像。 - 使用该 Docker 镜像实际构建站点。
- 将站点部署到 GitLab Pages。
主要的更改显然发生在 Dockerfile 中。下面是基于 Hugo 的新版本供参考:
FROM docker.io/hugomods/hugo:exts
ENV JAVA_HOME=/usr/lib/jvm/java-21-openjdk
ENV PATH=$JAVA_HOME/bin:$PATH
WORKDIR /builds/nfrankel/nfrankel.gitlab.io
RUN apk add --no-cache openjdk21-jre graphviz \ #1
&& gem install --no-document asciidoctor-diagram asciidoctor-diagram-plantuml rouge #2
- PlantUML 所需的包。
- 用于 Asciidoctor 图表和语法高亮的 Gems。
此时我本应该觉得有点不对劲,但它运行成功了,于是我继续下去。
关键问题
我在 Claude Code 和 Copilot CLI 的帮助下完成了迁移。整个过程用了几次会话,跨了一周,主要在晚上和周末进行。迁移期间,我经常请求一对一的对比,以避免回归。我的想法是并行构建 Jekyll 和 Hugo 站点,将它们都部署到 GitLab Pages 上,然后比较已部署的版本以找出最终的差距。
我更新了流水线以实现上述操作并触发了构建:
- Jekyll 构建: 稍微超过两分钟。
- Hugo 构建: 超过十分钟!
我简直不敢相信,于是再次触发构建,结果一致。
结果: 在我的 CI 环境中,Hugo 的速度远远慢于 Jekyll,这成为阻止我完成迁移的决定性因素。

我分析了日志以更好地了解问题所在。除了几条警告外,日志中没有任何解释慢速的原因。
│ EN
──────────────────┼──────
Pages │ 2838
Paginator pages │ 253
Non-page files │ 5
Static files │ 2817
Processed images │ 0
Aliases │ 105
Cleaned │ 0
Total in 562962 ms
当我询问 Claude Code 时,它指出我在文章中使用了 Asciidoc。虽然 Hugo 完全支持 Asciidoc(以及其他格式),但它会将除 Markdown 之外的格式委托给外部引擎。对于 Asciidoc,这个引擎是 asciidoctor。事实证明,这种方式在处理少量 Asciidoc 文档时还能接受,但在超过 800 篇时就出现了严重性能问题。我很快发现,我并不是第一个碰到这堵墙的人:这篇讨论串已经跨越了五年。
说我失望简直是轻描淡写。我把这项工作留在了一个分支上,未来可能会在冷静下来后将其删除。
结论
在进行迁移工作之前,我先尽职调查并确认了该工作的技术可行性。我通过阅读文档并与大型语言模型(LLM)聊天来完成这一步。然而,我在回滚之前就已经浪费了时间去做这项工作。
我对 Hugo 文档没有用粗体红字明确说明行为和性能影响感到有点愤怒。不过,这也是一个很好的教训,提醒我们在投入大量时间(即使是个人项目)之前,先检查此类问题。
进一步阅读:
最初发表于 A Java Geek 于 2026 年 2 月 15 日