经常有朋友问我这个博客是怎么做的,索性写一篇文章,从头到尾讲清楚。如果你也想搭一个自己的博客,希望这篇文章能帮到你。

先说结论 链接到标题

这是一个纯静态站点,没有服务器,没有数据库,成本极低:

项目方案
站点生成Hugo(Go 语言静态站点生成器)
主题Coder(git submodule 引入)
托管阿里云 OSS(对象存储)
加速阿里云 CDN
域名lixx.cn
搜索Pagefind(静态搜索索引)
评论Giscus(基于 GitHub Discussions)
访问统计Vercount(不蒜子兼容替代)
HTTPSacme.sh 自动签发免费证书 + CDN

每月费用:OSS 存储几毛钱 + CDN 流量几块钱,基本可以忽略不计。


一、为什么选 Hugo 链接到标题

市面上的博客方案太多了:WordPress、Hexo、Jekyll、Astro、Next.js……我选 Hugo 的理由很简单:

  1. 构建快 — 几百篇文章也是毫秒级构建,Hugo 是 Go 写的,编译型语言的碾压优势
  2. 零依赖 — 一个二进制文件,不需要 Node.js、Python、Ruby 任何运行时
  3. 主题生态成熟 — 有大量高质量主题可选,我用的 Coder 主题简洁清爽
  4. Markdown 原生 — 写文章就是写 Markdown,Git 管理,纯文本工作流

有人可能觉得 Hugo 的模板语法(Go Template)不如 JSX 灵活,但博客不需要多灵活,模板语法反而让你更专注内容。

二、项目结构 链接到标题

整个项目的目录长这样(精简版):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
lixx-coder/
├── hugo.toml              # 站点配置(唯一的配置文件)
├── content/
│   └── posts/             # 博客文章(Markdown)
│       ├── tech/          # 技术类
│       ├── life/          # 生活类
│       └── think/         # 随想类
├── layouts/               # 主题模板覆写
│   ├── home.html
│   ├── posts/single.html
│   ├── partials/
│   └── ...
├── assets/
│   ├── scss/              # 自定义样式
│   └── js/                # 自定义脚本
├── static/
│   └── images/            # 图片、头像、favicon
├── themes/
│   └── coder/             # 主题(git submodule)
├── deploy.sh              # 一键部署脚本
└── scripts/
    └── deploy-ssl.sh      # SSL 证书同步脚本

关键设计思路:

  • 主题通过 git submodule 引入,不直接编辑主题文件,方便后续升级
  • 所有自定义都在项目根目录完成layouts/ 覆写模板、assets/scss/ 添加样式
  • 单文件配置 hugo.toml,没有拆分成多个配置文件,一目了然

三、主题定制 链接到标题

3.1 主题加载方式 链接到标题

1
git submodule add https://github.com/luizdepra/hugo-coder.git themes/coder

主题以 git submodule 的方式引入,好处是:

  • 主题更新只需要 git submodule update --remote
  • 自己的修改全在 layouts/assets/ 里,和主题完全解耦
  • 不会出现合并冲突

3.2 模板覆写 链接到标题

Hugo 有一个很优雅的机制:在项目 layouts/ 下创建与主题相同路径的文件,就会自动覆写主题模板,不需要动主题源码。

比如我覆写了:

  • layouts/home.html — 首页(精简掉一些不需要的元素)
  • layouts/posts/single.html — 文章页(加入阅读量统计)
  • layouts/partials/footer.html — 页脚
  • layouts/partials/home/social.html — 社交链接(加了微信、小红书)
  • layouts/partials/home/avatar.html — 头像

3.3 自定义样式 链接到标题

样式通过 hugo.toml 中的 customSCSS 参数加载:

1
2
3
4
5
6
7
8
[params]
    customSCSS = [
        "scss/custom-fonts.scss",    # 字体栈
        "scss/cursor-theme.scss",    # 光标主题
        "scss/code-copy.scss",       # 代码块复制按钮
        "scss/page-views.scss",      # 阅读量样式
        "scss/search.scss"           # 搜索页样式
    ]

这些 SCSS 文件由 Hugo 独立编译,在主题 CSS 之后加载,所以不需要 !important 就能覆盖主题默认样式。

字体方面,我用的是 Inter(从 fonts.loli.net 国内镜像加载)+ 系统中文字体。这个组合在中文场景下显示效果很好,而且国内加载速度也不慢。

3.4 自定义脚本 链接到标题

同样通过 customJS 参数加载:

1
    customJS = ["js/code-copy.js", "js/typewriter.js"]
  • code-copy.js — 给代码块添加一键复制按钮
  • typewriter.js — 首页打字机效果

四、功能集成 链接到标题

4.1 全站搜索(Pagefind) 链接到标题

Pagefind 是一个静态搜索方案,构建时生成搜索索引,运行时完全离线,不需要任何后端服务。

集成方式很简单,部署脚本里加了一步:

1
npx pagefind --site public/ --glob "**/posts/**/*.html"

它会在 public/pagefind/ 下生成索引文件,前端通过 JavaScript 调用即可。搜索速度快,且不依赖第三方服务。

4.2 评论系统(Giscus) 链接到标题

评论系统选了 Giscus,它基于 GitHub Discussions,免费、无广告、支持 Markdown。

配置也简单,到 giscus.app 按引导配置,把生成的参数填进 hugo.toml

1
2
3
4
5
6
[params.giscus]
    repo = "Lixxcn/blog-comments"
    repoID = "R_kgDOR0UB1A"
    category = "Announcements"
    mapping = "pathname"
    lang = "zh-CN"

评论数据存在 GitHub Discussions 里,我不用担心数据丢失,也不需要自建数据库。

4.3 访问统计(Vercount) 链接到标题

早年用不蒜子(busuanzi),但服务不太稳定。后来换成了 Vercount,兼容不蒜子的 API,但后端更稳定:

1
    customRemoteJS = ["https://events.vercount.one/js"]

一行配置搞定,页面底部显示阅读量。

4.4 数学公式(KaTeX) 链接到标题

通过 Hugo 内置的 passthrough 扩展支持 KaTeX:

1
2
3
[markup.goldmark.extensions.passthrough]
    enable = true
    delimiters = { block = [['$$', '$$']], inline = [['$', '$']] }

$$...$$ 块级公式,$...$ 行内公式,写技术文章时非常方便。

4.5 代码高亮 链接到标题

Hugo 内置 Chroma 语法高亮,配置用 GitHub 风格:

1
2
3
4
[markup.highlight]
    style = "github"
    lineNos = true
    lineNumbersInTable = true

五、部署流程 链接到标题

这是我整个方案里最满意的部分——零服务器部署

5.1 架构图 链接到标题

1
2
3
4
5
6
7
用户浏览器
阿里云 CDN (lixx.cn)
阿里云 OSS Bucket (lixx-blog, 北京)
静态文件 (Hugo 生成)

没有 Nginx,没有 Docker,没有服务器运维。OSS 直接作为静态网站托管,CDN 做全球加速。

5.2 一键部署 链接到标题

运行 ./deploy.sh,脚本自动完成:

  1. 清理旧文件rm -rf public/
  2. 构建站点hugo --minify(压缩 HTML/CSS/JS)
  3. 构建搜索索引npx pagefind
  4. 同步到 OSSossutil sync --delete(增量上传,删除多余文件)
  5. 刷新 CDN 缓存aliyun cdn RefreshObjectCaches

整个过程大概 30 秒,从写完文章到上线,一条命令搞定。

5.3 部署脚本核心 链接到标题

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# 构建
rm -rf public/
hugo --minify

# 搜索索引
npx pagefind --site public/ --glob "**/posts/**/*.html"

# 上传到 OSS
ossutil sync public/ oss://lixx-blog/ --update --delete --force

# 刷新 CDN
aliyun cdn RefreshObjectCaches --ObjectPath "lixx.cn/" --ObjectType "Directory"

--delete 参数很重要,它会清理 OSS 上多余文件,确保线上和本地完全一致。

5.4 SSL/HTTPS 链接到标题

SSL 证书使用 acme.sh 自动签发免费证书(基于 Let’s Encrypt / ZeroSSL),配合 DNS 验证自动续期。证书更新后,运行 ./scripts/deploy-ssl.sh 同步到阿里云 CDN。全程自动化,不用手动操心证书过期。

六、写作工作流 链接到标题

我的日常写作流程:

  1. hugo new posts/tech/my-post.md — 创建文章
  2. 用编辑器写 Markdown
  3. hugo server -D — 本地预览(-D 包含草稿)
  4. 满意后改 draft = false
  5. ./deploy.sh — 一键发布

文章用 Git 管理,推到 GitHub 仓库备份。整个流程干净利落,没有任何多余步骤。

七、踩过的坑 链接到标题

7.1 Hugo 缓存问题 链接到标题

修改样式后有时候本地预览不生效,是因为 Hugo 缓存在 resources/_gen/ 里。删掉这个目录就好了。

7.2 字体加载 链接到标题

Google Fonts 在国内访问不稳定,所以用了 fonts.loli.net 镜像。如果镜像也挂了,会回退到系统字体,不影响阅读。

7.3 submodule 初始化 链接到标题

克隆仓库时忘了加 --recurse-submodules,主题目录是空的。需要手动执行:

1
git submodule update --init --recursive

7.4 OSS 文件清理 链接到标题

deploy.sh 中的 --delete 参数会删除 OSS 上不在 public/ 中的文件。所以不要手动往 OSS 上传文件,否则下次部署会被清理掉。

八、总结 链接到标题

这个博客的技术方案可以概括为:

Hugo 生成 + OSS 托管 + CDN 加速 = 零服务器、低成本、高性能的静态博客

没有运维负担,没有安全补丁,没有数据库维护。一台电脑、一个终端、一条命令,就能发布文章。

如果你也想搭一个类似的博客,照着这篇文章做就行。遇到问题可以给我留言,或者在 GitHub 上提 issue。