使用 Hugo+Congo 构建个人站点
目录
近期用 Hugo 配合 Congo 主题搭建了个人博客站点,经过简单配置和“装修”后目前已经上线运行。
本文简要记录配置与部署过程中遇到的问题与解决方案,并谈谈对 Hugo & Congo 设计思想的理解。
1. 配置过程 #
Hugo 的整体配置流程较为简单,大部分问题参考官方文档即可快速解决,因此这一环节仅做简要记录:
- 本地安装 Hugo,创建站点。
- 使用 Git Submodule 的方式安装 Congo 主题。
- 参照 Congo 文档完成配置: 基本配置 · Congo
- 将站点项目提交到 GitHub。
- 在 Vercel 上创建项目并关联 GitHub 仓库,配置自动部署。
- 针对站点做简单装修和扩展优化:
- 主页菜单添加 RSS
- 集成 Artalk 评论系统
- 集成 Google Analytics
- Git 忽略 public 和 resources
- 自定义 favicon
完成后,无论发布文章还是修改站点,只需将变更 push 到 GitHub,Vercel 即可自动部署。整个工作流自动、简洁,可将更多精力放在内容生产上,而且 Vercel 的免费额度足以支撑个人站点。
2. 过程问题排查和解决 #
以下为部署过程中遇到的问题,均通过搜索和 AI 辅助解决。
多语言相关 #
修改默认语言代码 #
我的母语为中文,借助当前强大的 LLM,可以轻松将文章转换成英文,创造更多连接的可能性。
Hugo 与 Congo 对多语言支持良好,且已支持简体中文。但 Congo 默认的简体中文语言代码为 zh-Hans
,在日常配置中略显繁琐。
为简化使用,我将 themes/congo/i18n/zh-Hans.yaml
复制到项目根目录的 i18n/
并重命名为 zh.yaml
(即 i18n/zh.yaml
)。这样等价于将简体中文的语言代码调整为 zh
,同时可直接编辑 i18n/zh.yaml
来覆盖主题默认的简体中文翻译。
双语文章的内容组织形式 #
对于多语言内容的组织,Hugo 提供多种方式。我采用最直观的“文件名配置法”:在同一个页面包目录下,用 *.语言代码.md
区分不同语言的页面。
例如一篇文章“我的精彩旅行”,目录结构如下:
content/posts/my-awesome-trip/
index.zh.md
(中文内容)index.en.md
(英文内容)featured.jpg
(中英文共享的图片)
需要在 index.zh.md
和 index.en.md
中设置相同的 translationKey
。Hugo 的多语言引擎会自动处理语言切换、URL 前缀、站点地图(会生成一个指向各语言 sitemap 的 sitemap index 文件)、分类与标签等细节。
修正中文阅读时间错误的问题 #
Hugo 支持“文章阅读时长”的计算和显示。但默认配置下,中文文章的阅读时长偏差较大,主要原因有二:
- Hugo 默认基于英文阅读速度(约 200 词/分钟),对中文不够准确。
- 中、日、韩文属于 CJK 语言,这类语言的字数计算与英文不同,需要特别配置与声明。
解决方法如下。
步骤 1:配置 Hugo 支持 CJK 语言 #
在 config/_default/hugo.toml
中开启 CJK 支持:
# 其他配置...
baseURL = "https://example.com/"
defaultContentLanguage = "zh"
hasCJKLanguage = true # 支持中文、日文、韩文字符统计
步骤 2:配置中文阅读速度 #
在 config/_default/languages.zh.toml
中设置中文阅读速度:
languageCode = "zh"
languageName = "中文"
languageDirection = "ltr"
weight = 1
title = "网站标题"
[params]
dateFormat = "2006-01-02"
reading_speed = 400 # 中文阅读速度:400 字/分钟
# 其他参数...
步骤 3:创建自定义阅读时间模板 #
创建文件 layouts/partials/meta/reading-time.html
,覆盖 Congo 主题默认模板:
{{- $readingSpeed := .Site.Language.Params.reading_speed | default 200 -}}
{{- $wordCount := .WordCount -}}
{{- $readingTime := math.Ceil (div (float $wordCount) (float $readingSpeed)) -}}
<span title="{{ i18n "article.reading_time_title" }}">
{{- i18n "article.reading_time" (dict "Count" $readingTime) | markdownify | emojify -}}
</span>
{{- /* Trim EOF */ -}}
该模板获取文章字数 $wordCount
,除以 reading_speed
后向上取整,并按多语言模板显示。
Vercel 部署 #
Build 时找不到 layout 文件 #
首次部署时出现如下 WARN 与 ERROR:
WARN found no layout file for "html" for kind "page": You should create a template file which matches Hugo Layouts Lookup Rules for this combination.
WARN found no layout file for "html" for kind "taxonomy": You should create a template file which matches Hugo Layouts Lookup Rules for this combination.
WARN found no layout file for "html" for kind "term": You should create a template file which matches Hugo Layouts Lookup Rules for this combination.
WARN found no layout file for "html" for kind "section": You should create a template file which matches Hugo Layouts Lookup Rules for this combination.
ERROR render of "/404" failed: ".../themes/congo/layouts/baseof.html:1:4": execute of template failed: template: 404.html:1:4: executing "404.html" at <partial "functions/warnings.html" .Site>: error calling partial: partial "functions/warnings.html" not found
Error: error building site: render: failed to render pages: render of "/" failed: ".../themes/congo/layouts/baseof.html:1:4": execute of template failed: template: index.html:1:4: executing "index.html" at <partial "functions/warnings.html" .Site>: error calling partial: partial "functions/warnings.html" not found
报错解读 #
- 构建时找不到任何布局(layout)文件。
- 渲染需要的
warnings.html
partial 也未找到。
原因 #
主题以 Git Submodule 引入。将仓库推送到 GitHub 时只包含了指向主题的“指针”,Vercel 默认不会拉取子模块,导致构建时 themes/congo
为空,Hugo 无法找到主题文件。
解决方案 #
在 Vercel 项目中添加环境变量以拉取子模块:
- Name: GIT_SUBMODULES_STRATEGY
- Value: 1
保存后重新部署。Vercel 会执行 git submodule update --init --recursive
,主题文件被完整拉取,构建即可成功。
部署后页面错乱 #
站点可访问,但页面布局错乱。浏览器控制台显示 main.bundle.min.css
加载失败。
原因 #
- Hugo 构建时的
baseURL
设为https://yandong.xyz/
(无www
),生成的资源链接是绝对路径,如https://yandong.xyz/css/main.bundle.min.css
。 - Vercel 域名配置将根域名
yandong.xyz
重定向到www.yandong.xyz
。 - 页面在
www
域名下加载非www
域名资源发生重定向与同源策略冲突,导致样式未加载。
解决方案 #
统一 Hugo 的 baseURL
为 https://www.yandong.xyz/
,与 Vercel 最终域名一致。重新部署后,资源链接与页面同源,请求不再跨域或重定向,问题消失。
3. 对 Hugo & Congo 设计理念的理解 #
组合 > 继承 #
Hugo 的渲染查找顺序为:项目 layouts
> 主题 layouts
> Hugo 内置。通过“组合式覆盖”替代传统的“继承”关系。就像“图层”的概念:只需在最顶层(项目)绘制要修改的部分,即可覆盖底层内容,无需修改或继承底层,实现高度自由且稳健的自定义。
配置分离 #
Hugo 与 Congo 将大量开关与选项(如社交链接、评论系统)放入配置文件而非模板硬编码。Congo 进一步细化常用配置:
languages.[语言].toml
管理多语言menu.[语言].toml
管理菜单params.toml
管理主题外观与参数- …
以内容为中心的资源组织 #
传统做法常将内容(.md
)与资源(图片)分离在 content/
与 static/
。Hugo 的页面包(Page Bundles)理念是:资源应与消费它的内容共存于同一目录。文章与配图在逻辑上不可分,在文件系统上亦应一致,这提升了可移植性与可维护性,并便于相对路径引用。
包裹复杂性 #
针对多语言、图片处理、多站点输出等复杂问题,Hugo 提供原生方案,用户无需过多处理底层细节与性能、兼容性问题。
4. 实践原则 #
基于上述理解,我个人会遵循形以下实践原则:
永远不要直接修改主题文件 #
始终在项目根目录的 layouts/
、assets/
、static/
中创建文件来覆盖或补充主题;配置集中于项目的 .toml
。使项目与主题解耦,后续升级主题时无需担心自定义丢失。
拥抱页面包 #
只要文章包含图片或其他资源,就为其创建目录,并将内容文件命名为 index.md
。使用相对路径 
引用资源,使内容单元(文章 + 图片)独立、完整、易维护,便于备份与迁移。
遵循 Congo 推荐的项目结构 #
为充分利用默认配置,你的项目结构应类似:
.
├── assets
│ └── css
│ └── compiled
│ └── main.css # 由构建生成
├── config # site config
│ └── _default
├── content # site content
│ ├── _index.md
│ ├── projects
│ │ └── _index.md
│ └── blog
│ └── _index.md
├── layouts # custom layouts for your site
│ ├── partials
│ │ └── extend-article-link.html
│ ├── projects
│ │ └── list.html
│ └── shortcodes
│ └── disclaimer.html
└── themes
└── congo # git submodule or manual theme install
以上为个人实践记录与理解,希望对你有所帮助。如遇到其他问题,欢迎留言交流。