嘶,总算是学校的事情忙完了,终于有点时间写写博客了
这个学期感觉一直都在和时间赛跑,没啥时间写博客,自己的项目也基本都断了
当然这些都是另外的话题了
如果之前有看过我博客的人,应该会发现现在网页大变样了
现在博客的框架从Hexo换到了Hugo
中间切换花了我很多时间,里面也有很多能说道说道的
需要注意的是,我的部署方案跟官方的不一样,所以部分配置会和官方文档有所出入
<0x00> 为什么要换框架
简单来说,也算是我闲着没事干
当然,之前Hexo的流程不是很舒服,写博客的话图片很不好引用
然后的话主题也不是很好看(我没时间去改主题)
然后正好想尝试下新东西,然后就看到了Hugo,于是就试了试
尝试之后发现这个框架使用体验确实舒适很多,于是就打算换框架了
换了框架后,好处主要有以下几点:
- 文章的图片资源可以更好的管理
- Obsidian更好的融合
- 舒适的预览体验
<0x01> 安装Hugo与新建站点
安装Hugo
以windows为例,其他系统只能自己看资料了
安装Hugo是很简单的
如果有安装scoop的话,可以直接敲命令安装
scoop install hugo-extended
这里安装的是带扩展的版本,因为我使用的主题需要这个
如果有安装winget,也可以直接敲命令安装
winget install Hugo.Hugo.Extended
如果上面两个包管理器都没安装,那么需要从Release中下载预构建的版本
找到带windows的压缩包下载,里面会有一个hugo.exe
然后丢到什么路径,添加到windows环境变量里面,这样就可以在命令行中调用了
新建Hugo站点
完成安装后,尝试新建站点来测试是否安装成功
在希望存放站点内容的位置打开终端
hugo new site TestBlog
这样会在这个位置创建叫TestBlog的文件夹,里面会包含hugo站点的结构
以上就完成了Hugo站点的搭建
<0x02> 配置Stack主题
这里使用的主题是Stack,简洁好看
路径约定
./表示存放所有Hugo站点的路径
所以./TestBlog就是存放TestBlog站点的路径
本文后面所有的路径都将按此表示
安装Stack主题
./TestBlog/themes是存放所有主题的路径
在此打开终端
git clone https://github.com/CaiJimmy/hugo-theme-stack.git
克隆主题仓库
然后回到./TestBlog,里面有个hugo.toml
将theme的值修改为'hugo-theme-stack'
配置头像
进入./TestBlog/themes/hugo-theme-stack
这里是Stack主题的文件
我们需要修改的头像在./TestBlog/themes/hugo-theme-stack/assets/img中
那个avatar.png便是我们我修改的图像
找自己的头像拖进去然后改名就可以了
配置网站图标
配置网站图标稍微麻烦点
首先进入./TestBlog/themes/hugo-theme-stack
创建叫static的文件夹,里面放入网站图标,这里取名favicon.webp
然后回到./TestBlog/themes/hugo-theme-stack,打开文件config.yaml
找到favicon,将值改为favicon.webp,也就是网站图标的文件名
配置社交媒体菜单
(指的是这个东西)

在./TestBlog/themes/hugo-theme-stack,打开文件config.yaml
在文件最后添加这些东西
menu:
main: []
social:
- identifier: github
name: 起个名吧
url: GitHub链接
params:
icon: brand-github
- identifier: bilibili
name: 起个名吧
url: bilibili链接
params:
icon: brand-bilibili
但仅仅这样是不行的,如果构建网页会说没有brand-bilibili.svg
所以我们需要添加这个svg
进入./TestBlog/themes/hugo-theme-stack/assets/icons,里面是所有的图标文件
新建一个文件,命名为brand-bilibili.svg,添加以下内容
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
stroke="currentcolor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
class="icon icon-tabler icons-tabler-outline icon-tabler-brand-bilibili">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M3 10a4 4 0 014-4h10a4 4 0 014 4v6a4 4 0 01-4 4H7a4 4 0 01-4-4v-6z"></path>
<path d="M8 3l2 3"></path>
<path d="M16 3l-2 3"></path>
<path d="M9 13v-2"></path>
<path d="M15 11v2"></path>
</svg>
(从别人博客薅的)
保存即可
如果要添加其他网站图标也是这样
<0x03> 文章路径与侧栏
Hugo的所有文章都是放在./TestBlog/content里面
Hugo支持页面包来对文章资源进行管理
页面包就是按路径对文章进行打包,一个文章只能访问自己页面包内的内容
这样就将每个文章独立开来,不像之前Hexo所有图片都在一个文件夹中
(或许Hexo也有办法实现,但我不知道)
修改默认文章目录
Stack主题默认指定./TestBlog/content/post为文章目录
这里我改成了./TestBlog/content/article
在./TestBlog/themes/hugo-theme-stack,打开文件config.yaml
找到mainSections将值改为article即可
侧栏部分
这里的配置建议参考Stack主题给的exampleSite配置
直接按page里面的结构配置即可
文章路径参考
我这的文章路径是这样的
content
├── article
| ├── posts
| | ├── 随便起的文章名字
| | | ├── picture
| | | | └── 1.png
| | | └── index.md
| | ├── ...
| | └── ...
| └── categories
| ├── Blog
| | ├── 随便起的文章名字
| | | ├── picture
| | | | └── 1.png
| | | └── index.md
| | ├── ...
| | └── ...
| ├── ...
| └── ...
├── page
| ├── about
| | └── index.md
| ├── archives
| | └── index.md
| ├── links
| | └── index.md
| └── search
| └── index.md
└── _index.md
<0x04> obsidian配置
用obsidian在./TestBlog/content创建仓库
obsidian里面需要配置的东西不多,主要是把链接设置为相对文件的路径
这样配置就可以了
由于使用页面包进行管理,所以所有的文章文件名都是index.md
这个会导致obsidian节点视图之类的功能显示的都是index,我目前没有很好的办法
<0x05> 部署到Github Page上
虽然官方文档有讲,但他们采用的是将整个站点push到github上
然后采用Github Action来在上面构建网页
这样的话如果Action脚本有误可能导致github page行为和本地测试不一样
我打算本地构建,然后将构建好的网页push到github上面,这样逻辑跟Hexo那套差不多
但Hugo没有这样的自动部署配置,所以要自己来
大致流程是在./TestBlog/public中初始化git仓库
添加远程git仓库
拉取后提交所有更改
如果需要切换分支的话再切换分支
之后只要构建后提交更改并上传即可
具体命令参考下面的自动化脚本
<0x06> 通过PowerShell实现自动化
因为是在windows平台,所以这里采用PowerShell来实现一些自动化
统一变量配置
因为会有好几个脚本,所以需要一个统一的变量配置
# configs.ps1
# 获取脚本文件夹路径
$global:ShellScriptDir = Get-Location
# 主目录
Set-Location ..
$global:SiteDir = Get-Location
Set-Location $global:ShellScriptDir
# 内容目录
$global:ContentDir = Join-Path -Path $global:SiteDir -ChildPath "content"
# 文章目录
$global:ArticleDir = Join-Path -Path $global:ContentDir -ChildPath "article"
# 一般文章目录
$global:PostsDir = Join-Path -Path $global:ArticleDir -ChildPath "posts"
# 分类文章目录
$global:CategoriesDir = Join-Path -Path $global:ArticleDir -ChildPath "categories"
# 基础URL
$global:BaseURL = "[...]"
# 远程Git仓库链接
$global:RemoteGitURL = "[...]"
# 目标分支
$global:TargetBranch = "[...]"
# 编辑器路径
$global:EditorPath = "[...]"
创建文章
因为希望每次创建文章都会自动创建对应的页面包,所以也需要一个脚本
# NewPost.ps1
param(
[string]
[ValidateNotNullOrEmpty()]
$PostName,
[string]
$CategoryName,
[bool]
$IsStartServer = $false,
[bool]
$IsCreatePictureFolder = $false
)
function ValidatedName {
param (
[string]
[ValidateNotNullOrEmpty()]
$Name
)
# 其他的特殊字符
$SpecialCharacters = [char[]]@(
"` "
"`!"
"`$"
"`%"
"`&"
"`'"
"("
")"
"*"
","
"-"
"/"
":"
";"
"<"
"="
">"
"?"
"@"
"["
"]"
"^"
"_"
"``"
"{"
"|"
"}"
"~"
)
# 因为我会写C#相关的文章,#有一些意义,对#做特殊替换
$Name = $Name.Replace("`#", "Sharp")
# 先每个替换成-
foreach ($Character in $SpecialCharacters) {
$Name = $Name.Replace($Character, "-")
}
# 返回时使用正则表达式匹配连续的-,并替换为单个-
return $Name -Replace '([-])+', '-'
}
# 保存当前的工作路径
$localDir = Get-Location
# 导入配置变量
. .\configs.ps1
# 切换工作路径
Set-Location $global:SiteDir
# 合法化路径名,不然图片会出问题
$validPath = ValidatedName -Name $PostName
# 普通文章创建
if ($CategoryName -eq "") {
# 新建Hugo文章
$newPostPath = Join-Path -Path "content\article\posts" -ChildPath (Get-Date -Format "yyyy")
$newPostPath = Join-Path -Path (Join-Path -Path $newPostPath -ChildPath $validPath) -ChildPath "index.md"
hugo new $newPostPath
# 生成图片文件夹路径
$newPostPicture = Join-Path -Path (Join-Path -Path $global:PostsDir -ChildPath $validPath) -ChildPath "picture"
}
# 需要分类的文章
else {
# 新建Hugo文章
$categoryPath = Join-Path -Path "content\article\categories" -ChildPath $CategoryName
$newPostPath = Join-Path -Path (Join-Path -Path $categoryPath -ChildPath $validPath) -ChildPath "index.md"
hugo new $newPostPath
# 生成图片文件夹路径
$categoryPath = Join-Path -Path $global:CategoriesDir -ChildPath $CategoryName
$newPostPicture = Join-Path -Path (Join-Path -Path $categoryPath -ChildPath $validPath) -ChildPath "picture"
}
# 需要创建图片文件夹的话就创建
if ($IsCreatePictureFolder) {
mkdir $newPostPicture
}
# 启动编辑器
# Start-Process $global:EditorPath
# 是否开启服务器预览
if ($IsStartServer) {
hugo server
}
# 返回之前的工作路径
Set-Location $localDir
使用示例
# 创建一篇普通的文章
.\NewPost.ps1 -PostName 从Hexo到Hugo-记录博客框架切换
# 创建一篇文章,并分类为Blog
.\NewPost.ps1 -PostName 从Hexo到Hugo-记录博客框架切换 -CategoryName Blog
运行后会创建对应的页面包
发布
这里涉及到两个文件,一个InitGit.ps1用来初始化git仓库,一个Deploy.ps1做推送
InitGit.ps1如下
# InitGit.ps1
param(
[bool]
$IsForcePush = $false
)
# 保存当前的工作路径
$localDir = Get-Location
# 导入配置变量
. .\configs.ps1
# 切换工作路径
Set-Location (Join-Path -Path $global:SiteDir -ChildPath "public")
# 初始化git
git init
git remote add origin $global:RemoteGitURL
git pull
git add .
git commit -m ("Init: " + (Get-Date -Format "yyMMdd-HH:mm"))
git branch -u $global:TargetBranch
if ($IsForcePush) {
git push origin HEAD:$global:TargetBranch --force
}
# 返回之前的工作路径
Set-Location $localDir
Deploy.ps1如下
# Deploy.ps1
param(
[bool]
$IsForcePush = $false,
[bool]
$IsClearDeploy = $false
)
# 保存当前的工作路径
$localDir = Get-Location
# 导入配置变量
. .\configs.ps1
# 切换工作路径
Set-Location $global:SiteDir
# 清除Hugo构建缓存
if ($IsClearDeploy) {
# 递归删除所有文件
Remove-Item -Path (Join-Path -Path $global:PublicDir -ChildPath "*") -Recurse
}
# 构建网页
hugo --gc --minify --baseURL $global:BaseURL
# 准备推送
Set-Location $global:PublicDir
# 没有初始化git的化就先初始化并强制推送
if (-not (Test-Path ".git")) {
. (Join-Path -Path $global:ShellScriptDir -ChildPath "InitGit.ps1") -IsForcePush $true
}
else {
git add .
git commit -m ("Deploy: " + (Get-Date -Format "yyMMdd-HH:mm"))
# 是否强制推送
if ($IsForcePush) {
git push origin HEAD:$global:TargetBranch --force
}
else {
git push origin HEAD:$global:TargetBranch
}
}
# 返回之前的工作路径
Set-Location $localDir
使用示例
# 正常的发布
.\Deploy.ps1
# 清空所有构建缓存发布
.\Deploy.ps1 -IsClearDeploy
运行即可推送到GitHub Page上
批量创建页面包路径结构
因为之前使用的是hexo,里面都是单独的markdown文件
如果自己手动一个一个移动并创建picture文件夹那就太累了
所以还是要写一个脚本完成自动化
# TransFromSingleFile.ps1
param(
[string]
[ValidateNotNullOrEmpty()]
$postDir
)
# 排除文件名单
$excludeList = "_index"
Get-ChildItem -Path $postDir -File | ForEach-Object {
if ($_.BaseName -notin $excludeList) {
# 创建文件夹并移动
$destDir = Join-Path -Path $postDir -ChildPath $_.BaseName
New-Item -ItemType Directory -Force -Path $destDir
Move-Item -Path $_.FullName -Destination (Join-Path -Path $destDir -ChildPath "index$($_.Extension)")
# 创建对应的picture文件夹
$newPostPicture = Join-Path -Path $destDir -ChildPath "picture"
mkdir $newPostPicture
}
}
使用示例
.\TransFromSingleFile.ps1 [某个路径]
运行可以为路径内所有文件创建同名文件夹,并将文件移动至对应文件夹后重命名为index.md
里面也会创建picture文件夹