*图:博客搭建全流程概览,从本地到线上的完整链路*
第一步:本地环境搭建
先装 Hugo。别去官网下那个压缩包,官方文档文档不够清晰。直接用包管理器:
“bash
macOS
brew install hugo
Ubuntu/Debian
sudo apt install hugo
Windows
choco install hugo-extende
d
`
装完验证版本:
`bash
hugo version
输出: hugo v0.121.1+extended linux/amd64
`
然后创建新站点:
`bash
hugo new site my-blog
cd my-blog
git
init
`
这里有个坑:官方模板库 PaperMod。网上教程清一色推荐,但我实际用下来发现它对中文支持有 bug——标签页的中文内容会乱码。我换成了 LoveIt 主题,兼容性好,还自带暗黑模式。
第二步:配置主题
``
git submodule add https://github.com/dillonzq/LoveIt.git themes/LoveIt
然后在 config.toml 里配主题:`toml
baseURL = "https://your-blog.com"
languageCode = "zh-cn"
title = "你的博客名"
theme = "LoveIt"
开启中文搜索
[params]
search = true
enablePWA = true # 顺手开了PWA,移动端体验更好
文章目录折叠
toc = true
tocAutoCollapse = true
`
这个设计真的反人类:languageCode 必须写 zh-cn 而不是 zh-CN,大小写错误会导致 RSS 订阅里的日期格式变成英文。我因为这个排查了俩小时。
第三步:写第一篇博客
`bash`
hugo new posts/hello-world.md
Hugo 会自动生成一个带 Front Matter 的 Markdown 文件。必须改的地方:
- draft: true
改为false,否则不发布 - date
用 ISO 8601 格式:2024-01-15T10:00:00+08:00
*图:Hugo Front Matter 配置截图,标注必填字段和常见坑点*
写文章时记住 Hugo 的 shortcode 机制。比如你要嵌入代码块:``
{{< highlight go "linenos=true" >}}
package main
func main() {
fmt.Println("Hello Blog")
}
{{< /highlight >}}
比用 “go 更灵活,还能加行号。
第四步:本地预览
“bash`
hugo server -D
-D 参数会包括草稿文章,方便预览。默认地址 http://localhost:1313。我习惯配个别名:`bash`
alias h="hugo server -D --bind=0.0.0.0"
这样局域网里也能访问,手机测样式。
第五步:部署到 GitHub Pages
先建两个仓库:
- username/username.github.io
(主站) - username/blog-source
(源码)
这个设计是为了隔离:源码仓库可以私有,生成的静态文件自动推送到 Pages 仓库。
配置 GitHub Actions:
`yaml
.github/workflows/deploy.yml
name: Deploy Blog
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: true
fetch-depth: 0
- name: Setup Hugo
uses: peaceiris/actions-hugo@v2
with:
hugo-version: 'latest'
extended: true
- name: Build
run: hugo --minify
- name: Deploy
uses: peaceiris/actions-gh-pages@v3
with:
personal_token: ${{ secrets.PERSONAL_TOKEN }}
external_repository: username/username.github.io
publish_dir: ./public
`
这个配置文件我改了六次才跑通。关键点是 personal_token 必须用 repo 权限的 PAT,而不是默认的 GITHUB_TOKEN。后者不能跨仓库推送。
另一个坑:GitHub Actions 的缓存策略。每次构建都重新下载主题和依赖,白白浪费 40 秒。加个缓存:
`yaml
- name: Cache Hugo modules
uses: actions/cache@v3
with:
path: /home/runner/.cache/hugo_cache
key: ${{ runner.os }}-hugo-${{ hashFiles('**/go.sum') }}
`
编译时间从 50 秒降到 8 秒。
第六步:自定义域名 + HTTPS
用 Cloudflare 做 DNS 和 CDN。为什么不用 GitHub Pages 自带的?因为它不支持 CNAME 的 apex 域名,而且国内访问慢。
步骤:
-> username.github.io有个小技巧:Cloudflare 的 Always Use HTTPS 和 Automatic HTTPS Rewrites 都打开。我第一次没开前者,结果访问 http:// 不跳转 https://,SEO 权重全丢给 HTTP 版本了。
第七步:SEO 优化
1. 自动生成 sitemap
Hugo 默认就有,但需要配下:
`toml
[mediaTypes]
[mediaTypes."application/sitemap"]
suffixes = ["xml"]
[outputFormats]
[outputFormats.sitemap]
mediaType = "application/sitemap"
isHTML = false
noUgly = true
`
2. 结构化数据
在 layouts/_default/single.html 加段 JSON-LD:`
html`
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BlogPosting",
"headline": "{{ .Title }}",
"datePublished": "{{ .Date.Format "2006-01-02T15:04:05Z07:00" }}",
"author": {
"@type": "Person",
"name": "你的名字"
}
}
</script>
这个能让 Google 在搜索结果里显示发布时间,点击率能提升 15-20%。
3. 图片优化
Hugo 内置图片处理,但默认是原图。我写了个 shortcode 自动压缩:
`
{{ $image := .Page.Resources.GetMatch (.Get "src") }}
{{ $small := $image.Resize "800x" }}
`
加载时间从 3.2 秒降到 0.8 秒,Lighthouse 性能评分直接从 65 蹦到 92。
第八步:自动化日常工作流
写了个脚本一键创建文章:
`bash
#!/bin/bash
new-post.sh
TITLE=$1
SLUG=$(echo $TITLE | sed 's/ /-/g' | tr '[:upper:]' '[:lower:]')
DATE=$(date +%Y-%m-%d)
FILE="content/posts/$SLUG.md"
cat > $FILE < title: "$TITLE" EOF echo "Created $FILE" 跑 ./new-post.sh “我的新文章” 还有个技巧:用 hugo list drafts | 优化前 | 优化后 | 方法 | *图:优化前后 Lighthouse 评分对比,左侧65分,右侧92分* Cloudflare 的自动压缩对 Hugo 生成的静态文件效果特别好。直接在 Speed -> Optimization 打开 Brotli 博客上线后我踩了个大坑:改了文章标题忘了同步 slug,导致旧链接全部 404。解决方案: ` hugo list all | while read file; do 这个小脚本每周五跑一次,自动报警。 还有个建议:定期备份。我的博客源码用 GitHub 私有仓库存着,但万一 GitHub 挂了怎么办?每周用 tar -czf blog-backup.tar.gz .` 打包传到另一个云存储。我不信任任何单一服务商。 博客是用来写的,不是用来折腾的。这套方案搭好后你只需要关心内容,其他一切自动化。现在打开终端,十分钟就能上线。
date: $DATE
draft: true
tags: []
categories: []
slug: "$SLUG"
` 就能生成带日期的文件。 查看所有草稿,防止漏发。我每周一早上跑一遍,把还躺在草稿箱里超过两周的文章删掉或补完。性能优化:从慢到快
|--------|--------|------|
| 首页加载 3.2s | 0.8s | 图片压缩+CDN |
| Google Pagespeed 65 | 92 | 开启 Brotli 压缩 |
| 构建时间 50s | 8s | 缓存依赖 |
| 首次内容绘制 2.1s | 0.6s | 预连接 CDN | 和 Auto Minify,文件体积能再减 30%。日常维护
bash检查所有文章的slug和title是否一致
title=$(grep "^title:" "$file" | cut -d' ' -f2-)
slug=$(grep "^slug:" "$file" | cut -d' ' -f2)
if [ -z "$slug" ]; then
echo "WARNING: $file 缺少slug"
fi
done
`总结一下,你可以立刻用的三个点