Hugo 使用指南

适用版本:Hugo v0.168.0(Extended)。命令以 macOS/Linux 的 shell 为例。根据 Hugo 官方文档整理,主题私有配置以实际主题仓库为准。

1. 安装与版本检查

macOS(Homebrew):

brew install hugo
hugo version
hugo env

Linux 可使用对应发行版软件包或 Hugo 官方发布的二进制文件。使用 SCSS/Sass 或某些主题资产管道时,需要确认安装版本包含 Extended 功能。

2. 创建项目

hugo new project myblog
cd myblog
git init

典型目录结构:

myblog/
├── archetypes/       # 新文章模板
├── assets/           # 需通过资源管道处理的资源
├── content/          # Markdown 内容
├── data/             # 数据文件
├── i18n/             # 主题界面翻译
├── layouts/          # 自定义模板,可覆盖主题模板
├── static/           # 原样复制到网站根路径
├── themes/           # 本地主题或 Git 子模块
├── hugo.toml         # 网站配置(也可使用 YAML 等格式)
└── public/           # 构建产物(运行 hugo 后生成)

Hugo 本体不附带完整博客外观。若没有可用主题或自定义布局,可能出现 found no layout file for "html" 的警告。

3. 使用现成主题(Git 子模块)

以下以官方快速入门采用的 Ananke 主题为例:

git submodule add https://github.com/gohugo-ananke/ananke themes/ananke

在 hugo.toml 中配置(不要重复声明同一个 TOML 键):

baseURL = 'https://example.com/'
title = '我的博客'
theme = 'ananke'

启动预览:

hugo server -D

不同主题的菜单、主页、参数、Hugo 版本和资产编译依赖不同。迁移配置时优先参考主题 README 和示例站点,不应把另一款主题的 [params] 原样照搬。

Git 子模块维护

新机器克隆:

git clone --recurse-submodules <仓库URL>

已有克隆补齐子模块:

git submodule sync --recursive
git submodule update --init --recursive

更新子模块(会跟踪其配置的远端分支,应检查变更后提交):

git submodule update --remote --merge
git diff --submodule
git add .gitmodules themes/
git commit -m 'Update Hugo theme'

对子模块的 Git URL 做迁移时:先修改 .gitmodules 中的 url,然后执行 git submodule sync --recursive。CI 网络不稳定时可以改用可访问的 Git 镜像,但要保证镜像具有所需提交对象;也可以在克隆主仓库后自行初始化子模块。

4. 创建和编辑文章

hugo new content posts/hello-world.md

示例文章:

---
title: "Hello World"
date: 2026-10-17T12:00:00+08:00
draft: false
description: "文章简介"
tags: ["Hugo", "博客"]
categories: ["技术"]
---

这是正文。

## 一级章节

**加粗**、*斜体*、[外部链接](https://gohugo.io)。

重点字段:

字段用途
title标题
date文章时间
drafttrue 表示草稿,默认生产构建不发布
description简介,是否展示由主题决定
tags、categories分类法,具体页面展示由主题决定
slug自定义 URL 末段(实际路径也受 permalink 配置影响)

注意:未来日期文章默认也可能不会纳入生产构建;需要检查日期、时区及 --buildFuture。

图片与静态文件

全站静态文件放 static/images/logo.png,文章引用:

![Logo](/images/logo.png)

页面资源包(page bundle)可使用:

content/posts/hello/
├── index.md
└── cover.jpg

index.md 中写 ![封面](cover.jpg)。若要用主题的图片处理、缩略图等功能,仍需遵循该主题的页面资源约定。

5. 本地开发与构建

hugo server                  # 预览已发布内容
hugo server -D               # 包含草稿
hugo server --bind 0.0.0.0   # 允许其他设备连接;注意网络访问控制
hugo                         # 输出到 public/
hugo --gc --minify           # 常用生产构建
hugo -d dist                 # 输出到 dist/

Hugo 的构建命令不会在构建前自动清空输出目录。如果删除文章、修改 URL 或切换语言,旧文件可能保留。推荐在 CI 的临时构建目录中清空产物再执行构建,而非不加检查地清理任意路径。

rm -rf public
hugo --gc --minify

只有确认 public/ 是纯构建产物、没有用户数据时,才执行上述删除操作。

6. 多语言站点

以下展示中文与英文的基本配置,支持的具体语言菜单和切换方式取决于主题:

baseURL = 'https://example.com/'
title = '我的博客'
defaultContentLanguage = 'zh-cn'
defaultContentLanguageInSubdir = false

[languages]
  [languages.zh-cn]
    languageName = '简体中文'
    languageCode = 'zh-CN'
    weight = 1
    title = '我的博客'
  [languages.en]
    languageName = 'English'
    languageCode = 'en-US'
    weight = 2
    title = 'My Blog'

按语言目录划分内容的一种组织方式:

content/
├── zh-cn/
│   └── posts/hello.md
└── en/
    └── posts/hello.md

使用上述语言目录布局前,应结合多语言内容目录配置或语言挂载确认内容正确归属。更简便、无需额外挂载的方式是同目录使用翻译文件名 hello.zh-cn.md 和 hello.en.md;默认语言也可按项目配置安排 URL。

推荐:对于已经存在 content/posts/ 的站点,先采用文件名后缀法:

content/posts/
├── hello.zh-cn.md
└── hello.en.md

翻译页面最好设置一致的 translationKey(仅在无法通过文件路径直接关联时需要),避免多语言菜单指向错误页面。

7. Markdown 中使用 HTML

Hugo 默认使用 Goldmark。若日志出现 Raw HTML omitted while rendering,说明 Markdown 中的原始 HTML 未被渲染。只有信任文章内容时才在 hugo.toml 中开启:

[markup.goldmark.renderer]
  unsafe = true

开启后,文章内嵌 HTML 将参与输出;如果内容来自不可信投稿源,需考虑脚本注入风险。

8. Git 与 Gitea Actions 发布

推荐将源码仓库(包括 .gitmodules、content/、hugo.toml 等)与静态发布仓库或分支分开。CI 的典型流程:

push 到源码 main
       │
       ▼
拉取源码与主题子模块
       │
       ▼
安装指定版本 Hugo
       │
       ▼
清理临时构建输出,执行 hugo --gc --minify
       │
       ▼
将 public/ 文件提交到发布仓库 main 或发布分支
       │
       ▼
Caddy / Nginx 对静态目录提供服务

可先在构建容器中验证这些命令:

git submodule sync --recursive
git submodule update --init --recursive
rm -rf public
hugo --gc --minify
find public -maxdepth 2 -type f | head

Gitea Actions 示例工作流必须根据 act_runner 的标签、容器镜像、Git 认证、权限、Hugo 安装路径与目标分支 单独配置。不要假设 GITHUB_SHA 或自定义 COMMIT_SHA 在所有 shell 步骤中自动存在;脚本采用 set -u 时,未定义变量会直接导致构建失败。获取源码提交值可在已 checkout 的 Git 仓库中执行:

SOURCE_SHA="$(git rev-parse HEAD)"

目标发布仓库使用单独的工作目录,防止误删除源文件;推送前检查分支的非快进冲突,不建议将无检查的 git push --force 作为通用发布策略。

9. 常见故障排查

9.1 found no layout file for "html"

原因通常是主题没有被正确加载、主题缺少对应模板,或者配置文件中的 theme 名称和 themes/ 目录不匹配。

ls -la themes/
cat .gitmodules
hugo config | grep -i theme
hugo --logLevel debug

确认主题目录内实际存在 layouts/ 等模板文件,并检查主题自己的使用说明。不要通过忽略警告解决空白站点。

9.2 Raw HTML omitted

按第 7 节检查 markup.goldmark.renderer.unsafe,也可尽量将原始 HTML 改为 Markdown 或 Hugo shortcode。

9.3 Git 子模块目录为空

git submodule status --recursive
git submodule update --init --recursive

若报网络错误,检查 .gitmodules 中 URL、认证和构建容器内 DNS/代理,而不仅是宿主机网络。

9.4 页面没发布

核对文章的 draft、日期、过期时间、语言以及目标主题路由;检查:

hugo list all
hugo list drafts
hugo list future
hugo list published

9.5 CI 构建成功但发布内容未变化

检查 public/ 是否包含预期 HTML、发布分支是否更新、Web 根目录是否指向最新部署位置,以及浏览器/CDN 是否缓存旧内容。不要先认定是 Hugo 缓存问题。

10. 推荐的日常工作流

# 1. 拉取更新(包括子模块)
git pull --ff-only
git submodule update --init --recursive

# 2. 新建文章
hugo new content posts/new-post.md

# 3. 编辑并本地预览
hugo server -D

# 4. 将文章 front matter 中 draft 改为 false

# 5. 提交推送(CI 自动构建/发布)
git add content/
git commit -m 'Add new post'
git push

11. 参考资料