使用 Hugo + GitHub Pages 搭建个人博客

作者: 风筝 / 2023-06-02

GitHub Pages, Hugo, 个人博客

我的博客地址,https://www.moonkite.cn

很多人都想创建自己的个人博客或网站,但是由于种种原因,都被劝退了。

比如没有流量没人看、服务器域名要花钱等等,如果你是因为花钱被劝退了,那现在有很多免费的方案可选,今天就介绍一种,使用 Hugo + GitHub Pages 方式免费搭建个人博客,真的是免费的。

前提是你要会操作 GitHub,不过这不是什么难事儿,由于对于技术人来说,简直是基本操作。

为什么选 Hugo + GitHub Pages

什么是 Hugo

Hugo 是一个快速、现代且高度可配置的静态网站生成器。它是使用 Go 语言开发的,并以简单易用、高效构建和渲染静态网页而闻名。Hugo 的设计目标是提供一个简洁、高性能的工具,以便开发人员可以轻松创建和管理各种类型的静态网站。

与之类似的还有 Hexo 。

Hugo 的主要特点包括:

  1. 快速构建:Hugo 使用并行处理和基于文件变化的增量构建技术,可以在几秒钟内生成大型网站,提供出色的构建速度和性能。
  2. 灵活可配置:Hugo 提供丰富的配置选项和灵活的主题系统,允许开发人员根据自己的需求进行定制和扩展。
  3. Markdown 支持:Hugo 使用 Markdown 作为主要的内容格式,方便作者使用简洁的语法编写内容,并将其转换为美观的静态网页。
  4. 多语言支持:Hugo 支持多语言网站,可以轻松创建多语言版本的网站,并提供多语言内容管理和翻译支持。
  5. 主题和布局:Hugo 提供了丰富的主题和布局选项,使开发人员能够快速创建具有吸引力和响应式设计的网站。
  6. 内置开发服务器:Hugo 提供了一个内置的开发服务器,可以在本地预览和调试生成的网站,方便开发和调试过程。

我们不用会 Go 语言、不用会前端,只要会用 Markdown 写字就好了。

Hugo 官网:https://gohugo.io/

官网上可以找到几百种的主题,各种风格应有尽有。

什么是 GitHub Pages

GitHub Pages 是 GitHub 提供的一项托管静态网站的服务。它允许用户将自己的代码仓库中的静态网页文件(如 HTML、CSS、JavaScript 等)直接部署为一个在线可访问的网站。

以下是 GitHub Pages 的主要特点和用途:

  1. 免费托管:GitHub Pages 是免费的,用户可以将自己的静态网站免费托管在 GitHub 平台上。
  2. 简化部署流程:使用 GitHub Pages,用户只需将静态网页文件上传到 GitHub 上的特定仓库,并配置相应的设置,即可自动部署网站,无需自己搭建服务器或配置复杂的环境。
  3. 版本控制:由于网站文件存储在 GitHub 仓库中,用户可以充分利用 Git 的版本控制功能,轻松管理和追踪网站文件的变化。
  4. 自定义域名:GitHub Pages 支持自定义域名,用户可以将自己已经拥有的域名与 GitHub Pages 上的网站关联,实现个性化的访问地址。
  5. 多种发布方式:GitHub Pages 支持多种方式发布网站,包括使用现有的 Git 仓库作为源码、使用 Jekyll 静态网站生成器等。
  6. 兼容 Jekyll:GitHub Pages 默认支持 Jekyll,一个基于 Ruby 的静态网站生成器,可以帮助用户更方便地创建和维护静态网站。

免费,而且可用 GitHub 仓库作为源码库生成对应的静态网站,正好可以结合 Hugo 使用。

本地安装 Hugo

首先是安装 Go 环境,直接到 Go 官网下载安装包安装就好了。https://go.dev/learn/

接下来安装 Hugo。

MacOS 安装

brew install hugo

Window 安装

choco install hugo-extended

还可以从源码直接安装

go install -tags extended github.com/gohugoio/hugo@latest

最后验证 Hugo 安装状态

hugo version

有下面这种类似的输出说明安装成功了。

hugo v0.111.3+extended darwin/amd64 BuildDate=unknown

选定一个主题

Hugo 官网提供了几百种主题样式可供选择。https://themes.gohugo.io,到上面选一个你喜欢的风格。

大多数主题还可以预览 demo

选定了就好了,一会儿会用到。

创建本地项目

创建项目主体

Hugo 是一个工具,安装完之后,需要用它提供的命令创建出博客的主要目录和文件结构。

进入你想要放置项目的目录中,然后在终端命令行中执行下面的命令,进行博客项目的创建:

hugo new site 替换为你的博客名称
# 例如
hugo new site fengzheng-blog

命令执行完成后,你会在当前目录下看到一个以你博客名称命名的文件夹,里面的目录结构大概是这样子的。

image-20230628155232577

这样一个主体结构就出来了,但是还差一步,就是主题,主体结构好比是骨骼,主题就是一套皮肤。

集成主题

刚才上面已经选定了你心仪的主题了,一般主题下面会有使用介绍。比如我的博客用了 hugo-theme-den 这个主题,点进主题详情后,可以看到介绍和使用方式。

接下来,下载主题文件到你创建的项目中,下载到 themes目录下。

git clone https://github.com/shaform/hugo-theme-den themes/hugo-theme-den

下载后的目录结构:

有的主题说使用git submodule add这种添加子模块的方式添加主题,这样做的好处是将主题仓库作为子模块加到项目中,当主题有更新后,可以及时更新。

我不太喜欢用这种方式,在挑选主题的时候就是看的当下的主题样式,万一将来主题被大改后,那就不是我想要的了。而且,使用这种方式,在自动部署的时候可能会出现各种各样的问题。

所以,我还是把主题下载到我本地的项目中,想做定制,就在本地项目的主题中定制,发布的时候就和项目主体一起发布了,很方便,也很灵活可控。

主题地址:https://themes.gohugo.io/themes/hugo-theme-den/

配置网站+本地调试

最终下载下来的主题目录是这样的

image-20230628161827409

全局配置

首先将主题目录下的 config.toml文件复制到项目根目录下,这个配置文件就用来配置网站的全局配置了,比如host、标题、菜单、默认语言等等。

我用 hugo-theme-den 这个主题的配置做一个介绍。

以下是 Hugo 配置文件中各项设置的名称、值和说明:

名称说明
baseURLhttps://moonkite.cn网站的基础 URL,引用的本地图片、css等,将会以这个地址作为 host
title“古时的风筝”网站的标题
theme“hugo-theme-den”网站所使用的主题
enableRobotsTXTtrue生成 robots.txt 文件,用于控制搜索引擎爬虫的访问
enableEmojitrue启用 Emoji 表情支持
hasCJKLanguagetrue检测 CJK(中文、日文、韩文)语言用于字数统计等功能
preserveTaxonomyNamestrue不将标签名转为小写
rssLimit20限制 RSS 订阅中的条目数量
disablePathToLowertrue禁止将路径转为小写
paginate20每页显示的条目数量(用于归档、标签和分类)
paginatePath“page”分页路径的前缀
PygmentsCodeFencestrue启用代码块的语法高亮
PygmentsUseClassestrue需要用于 shhighlight shortcode
disqusShortname""Disqus 评论系统的 shortname
googleAnalytics""Google Analytics 的跟踪 ID
defaultContentLanguage“zh-cn”默认使用的语言
defaultContentLanguageInSubdirfalse默认语言是否在子目录中
permalinks.posts“/:year/:month/:day/:slug/”文章的永久链接格式
permalinks.categories“/category/:slug/”分类的永久链接格式
permalinks.tags“/tag/:slug/”标签的永久链接格式
permalinks.pages“/:slug/”页面的永久链接格式
author.name“风筝”作者的名称
sitemap.changefreq“weekly”sitemap.xml 文件的更新频率
sitemap.priority0.5sitemap.xml 文件的优先级
sitemap.filename“sitemap.xml”sitemap.xml 文件的文件名
params.since“2023”网站创建时间
params.rssFullContenttrue在 RSS 订阅中使用完整内容而不是摘要
params.keywords[“Hugo”, “theme”,“编程”,‘java’,‘ChatGPT’,“程序员”,‘开发’]网站的关键词
params.description“一个程序员的个人博客”网站的描述
params.logoTitle" "在左上角显示的 Logo 标题
params.siteLogoImage""在 Logo 标题旁边显示的 Logo 图片
params.headerImage“images/background.png”头部背景图片
params.showAuthorCardtrue是否在文章下方显示作者信息
params.commentstrue是否启用评论功能
params.showMenuLanguagestrue是否显示多

本地启动

先做一些基本设置之后呢(其实可以先什么都不改,先看看效果),就可以启动项目了,使用下面的命令启动

hugo server

之后,看到下面这样的输出,说明启动成功了。

......
Running in Fast Render Mode. For full rebuilds on change: hugo server --disableFastRender
Web Server is available at http://localhost:1313/ (bind address 127.0.0.1)
Press Ctrl+C to stop

现在在浏览器打开 http://localhost:1313,就能看到效果了。当然了,刚开始肯定只有基础样式,没有内容。

image-20230628163325001

启动之后,之后做的修改会自动热部署,不用重启应用,除非有些配置的修改。什么配置呢,就是那种你发现改了,刷新页面了,但是没起作用,很多时候就是需要重启了。

Ctrl+C停止应用,然后hugo server重新启动。

定制化(可选)

如果你使用的是我用的这个主题,可以配置作者卡片和相关文章。

配置作者卡片和相关文章

大部分博客主题都有这个设置,注意看选用主题的使用说明或示例配置就好了。

在每一篇文章的底部都可以出现相关文章和作者卡片,例如下面这样。

相关文章

config.toml配置中做如下配置,注意 toml 文件的格式。

[params]
	enableRelated = true

作者卡片

首先启用 showAuthorCard配置

[params]
  showAuthorCard = true 

然后,在根目录的 data/authors子目录下(如果没有 authors目录,则需要手动创建),添加一个作者的配置,可以有多个作者,一个作者对应一个配置文件。

例如在 data/authors目录下创建 fengzheng.toml的文件,配置上内容

url = "https://www.moonkite.cn"

[name]
display = "风筝"

[image]
url = "images/person.jpg"

[zh-cn]
description = "作者描述"

评论功能

很多主题都默认带评论功能,比如 Disqus,例如下面的配置。你需要到 Disqus 官方上申请账号,然后配置上下面的配置就好了。

disqusShortname = ""         # disqus_shortname

但是据说广告太多,国内用户又这么不喜欢广告,所以在国内这个评论系统基本上没人用。

与它类似的叫做Giscus的评论系统,没有广告,完全免费。具体可以参考官网进行集成 https://giscus.app/zh-CN

Utterance

我用的就是这个评论系统,集成简单,有个 GitHub 仓库就行了,它是用的仓库的 issue 功能来改造的。

1、首先在 GitHub 中创建一个空白仓库就行

2、然后,点击这个地址 https://github.com/apps/utterances,进入安装页,点击Configure。

3、选择刚才创建的仓库,然后保存

4、最后找到主题目录下的/layouts/partials/comments.html,将里面的内容替为将下面的内容


<script src="https://utteranc.es/client.js"
        repo="github账号名称/仓库名称"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async>
</script>

其中 repo要配置成你创建的仓库,前面是你账号名称,后面是仓库名称。

菜单和对应的目录

菜单也是在config.toml中配置,每个主题的配置可能略有不同,我用的这个主题的配置是下面这样子:

[languages.zh-cn]
  languageCode = "zh-cn"
  languageName = "简体中文"
  contentDir = "content/cn"
  weight = 2

  [languages.zh-cn.params]
    description = "一个程序员的喃喃自语"

  [[languages.zh-cn.menu.main]]
    name = '<i class="fas fad fa-h-square"></i>主页'
    weight = 1
    identifier = "home"
    url = "/"

  [[languages.zh-cn.menu.main]]
    name = "<i class='fas fa-yin-yang'></i>生活随笔"
    weight = 10
    identifier = "notes"
    url = "category/notes"

一般主题都支持多语言的,languages.zh-cn表示中文,其对应的文章的存放目录就是content/cn

languages.zh-cn.menu.main是中文语言下的菜单,一个菜单包括如下几个配置:

属性说明
name展示名称,可包含html
weight菜单项权重,用于确定显示顺序
identifier菜单项标识符
url菜单项链接地址

以上是 Hugo 菜单设置中 “主页” 项的属性说明。其中,name 表示菜单项的显示名称,weight 用于指定菜单项的排序权重,identifier 是菜单项的唯一标识符,url 则指定了菜单项的链接地址,除了主页指向根目录外,其他的都指向 content/cn的子目录。

例如,生活随笔的 url 是 category/notes,它的完整路径就是 content/cn/category/notes

每创建一个目录后,要在其中添加一个名称为 _index.md的文件,里面内容就是为了显示这个菜单进去的列表页标题,例如下图中间的生活随笔四个字。

---
title: 生活随笔
--- 

最后出来的效果如下:

添加文章

配置完菜单和对应的文章目录后,就可以添加文章了。

Hugo 中的文章都是 Markdown 格式,之后 build 的时候会将 markdown 文件按照格式转换成 HTML 。

加一篇文章,那就是创建一个 markdown 文件,文件的名称其实是不影响展示的,只为你自己辨认。真正影响展示的在 markdown 文件的内容的最上方定义。

例如我在生活随笔这个栏目下添加了一个文件,名称无所谓,不影响展示。

内容部分,要在开头加入类似下面你的配置,生成HTML的时候需要。

---
title: "这次没躲过去,阳了"
date: 2023-06-02T08:56:23+08:00
draft: false
description: 2023 年 5 月 25 日,阳了
authors:
    - "风筝"
comment: true
---
属性说明
title文章标题,用来展示
date文章发布日期,用来展示,日期越晚,展示越靠前
draft是否为草稿
description文章描述
authors文章作者

最终的效果如下:

编译和发布

使用 hugo build命令,会在根目录下生成 build目录,这个目录就是 GitHub Pages 所需的格式了。

GitHub Pages 就是读取一个特定仓库的内容,然后做展示。这个特定仓库有什么特点呢,就是仓库名称,仓库名称必须是你的GitHub账号名称.github.io,例如alibaba.github.ioalibaba就是账号名称,可以在 URL上看出来。

当然了,你不能用别人的仓库,必须是你自己的。

1、在你的 GitHub 中创建仓库,注意名称一定要按照上面说的那个格式。

2、进入刚刚 build 完成后的 public目录,然后初始化仓库,关联远程仓库,提交代码。

git init
git commit -m "first commit"
git branch -M main
git remote add origin https://github.com/username/username.github.io
git push -u origin main

3、如果没有意外的话,你就能看到远程仓库已经有了你提交的内容。如果有意外的话,大部分是 GitHub 提交的问题,自行解决就OK了,相信自己。

4、在浏览器输入username.github.io,就能看到部署的博客了。例如我的博客的默认域名是https://huzhicheng.github.io

之后,如果有改动的话,执行 hugo build本地构建,然后提交代码到远程仓库。重复这个步骤就行了。

好像也还算方便。但是,还有更方便的,那就是自动发布。

配置自动发布流程

自动发布需要再创建一个仓库,用来存放项目源文件,不是build之后的,这个仓库可以是私有的,这样一来,项目也有版本管理了,岂不妙哉。

整个发布流程大概是这样子的。

1、首先创建一个私有仓库,作为项目源文件仓库,用于管理未经编译的代码。

创建好仓库后,按照仓库的提示,将本地的源代码目录和远程仓库关联上。

2、然后在根目录的.github目录下创建workflows的子目录,并在其中添加一个deploy.yml的文件。

里面的内容如下:

name: deploy # 名字随意

on:
  push:
    branches: [ "main" ]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
        with:
          submodules: false  # Fetch Hugo themes (true OR recursive) 获取submodule主题
          fetch-depth: 0    # Fetch all history for .GitInfo and .Lastmod

      - name: Setup Hugo	# 步骤名自取
        uses: peaceiris/actions-hugo@v2	# hugo官方提供的action,用于在任务环境中获取hugo
        with:
          hugo-version: 'latest'	# 获取最新版本的hugo
          # extended: true

      - name: Build
        run: hugo --minify	# 使用hugo构建静态网页

      - name: Deploy
        uses: peaceiris/actions-gh-pages@v3	# 一个自动发布github pages的action
        with:
          external_repository: username/username.github.io	# 发布到哪个repo
          personal_token: ${{ secrets.ACTION_ACCESS_TOKEN }}	# 发布到其他repo需要提供生成的personal access token
          publish_dir: ./public	# 因为hugo默认生成静态网页到public文件夹,所以这里发布public文件夹里的内容
          publish_branch: main	# 发布到GitHub Pages关联仓库的哪个branch

注意,上面的文件只需要将 external_repository修改成你自己的 GitHub Pages 关联仓库就好,其他都不用动。

3、创建 Personal Token

进入 GitHub,点击你自己的头像,点击 Settings

点击Developer Settings

点击创建一个 Token

然后设置名称、有效期和权限。名称随意,方便以后辨认。有效期可选,我为了以后不改,就设置了无限期,当然为了安全性考虑,这是不建议的。

然后勾选 repoadmin:repo_hook这两项。

最后,会生成一个 token。一定要记录下来,后面会用到,就显示这一次,以后就看不到了。

4、在源码仓库设置token,也就是那个第1步创建的那个仓库。

进入这个仓库的 Settings->secrets and variables->Actions,在这里点击New repository secret

image-20230628185008522

注意,Name 是有讲究的,是刚才第2步的 deploy.yml文件中设置的

personal_token: ${{ secrets.ACTION_ACCESS_TOKEN }}

就是 secrets. 后面的部分。

而 Secret 是第3步创建的 Person Token,就是说了一定要保存的那个Token。

5、提交代码,自动发布。

之后,我们将代码提交,然后在源码仓库中的Acitons选项中,可以看到提交的自动部署流程。

并且有每一次提交的自动部署记录。

这样一来,每次修改完成,或者添加完文章,只需要提交源码仓库就好了,自动发布流程会自动打包部署,然后推送到 GitHub Pages 关联仓库,稍等片刻,刷新页面,就可看到更新后的内容了。

自定义域名(可选)

如果你不想用默认的username.github.io域名,那可以设置自已的域名,域名就要花钱了,不过非 .com后缀的域名一般都很便宜,几十块钱、甚至几块钱一年的都有,只要不是字符数太少的,那种就不要想了。

购买域名

买域名的话,平台有很多,国内就阿里云就好了。

国外的CloudflareNameSiloGoDaddy 都可以。

国外的买了就可以用,国内的话,还需要备案,备案需要一点时间。

我这个 moonkite.cn 域名买了很多年了,之前一直用二级域名当图床啊、测试服务这些用,这次主域名终于派上用场了。

解析域名

如果你是用的阿里云的话,进入域名列表页,点击域名后面的「解析」按钮。

添加两条记录,都是 CNAME 类型的,也就是别名类的,一个域名解析到另一个域名。

主机记录选www@,记录值就是你的 GitHub Pages 默认域名username.github.io,记住换成你自己的 GitHub 名字。

最后添加完成这两个 CNAME 解析如下。

说是等10分钟,基本上都不用那么久,片刻即可生效。

配置域名

域名解析配置好后,要在仓库中进行设置。

打开GitHub Pages 关联仓库,也就是 username.github.io 那个,点击仓库的 Settings,在左侧菜单中选择Pages

然后在下方的Custom domain这里配置上你自己的域名,配置之后,会立即检测DNS,成功后,会有绿色的提示。

之后,在浏览器输入你的域名,就可以访问了。

大功告成。

自动更改自定义域名

但是,如果你用的是自动部署方式,会发现每次提交代码后,自定义域名都被改回默认域名了。这不白干了吗,难道每次都要配置一下?

当然不用了,你只需要在项目的根目录中找到 static目录,在其中创建一个名称为 CNAME的文件,注意,没有文件后缀。在其中写入你自己的域名即可,之后每次添加文章、修改样式,再重新提交代码,自动部署后,域名就不会改为默认的了。

相关文章

终于知道公钥、私钥、对称、非对称加密是什么了
什么时候用 Runnable?什么时候用 Callable ?
如何用 Docker 快速搭建开发环境
什么是零拷贝|Java中的零拷贝
剑走偏锋,无头浏览器是什么神奇的家伙
风筝

作者

风筝

古时的风筝,一个平庸的程序员,主语言 Java,第二语言 Python,其实学 Python 的时间比 Java 还要早。喜欢写博客,写博客的过程能加深自己对一个知识点的理解,同时还可以分享给他人。喜欢做一些小东西,所以也会一些前端的东西,React、JavaScript、CSS 都会一些,做一些小工具还够用。