为什么要迁移博客
- 自从给博客添加了许多图片和 js 内容,Hexo 的渲染速度就升上了 1 s,文章只会越来越多,速度只会越来越慢,早换早解脱。
- Hexo 的包维护起来太麻烦了,上次更新依赖我直接重新下了 node. Js,每次更新都很笨重,而且有时候需要的插件和主题不兼容,(以我贫乏的前端知识)也不知道怎么改,技术上太黑盒了。
准备工作
-
首先明确需求:我希望不需要新建 GitHub 仓库,继续在原有的仓库中托管博客,这样不用再搞一遍 SSH 相关,只需要清空原来的仓库,把 Hugo 生成的新博客页面放进去就行了。在电脑上,我新建了一个文件夹存放 Hugo 的博客内容,废弃掉原有的 Hexo 博客内容文件夹。
-
保证网络连接:挂代理后发现无法
git push
了,参考网络上的回答在系统-网络与 Internet-代理-手动设置代理中获得当前代理使用的端口号,使用git config --global http.proxy http://127.0.0.1:端口号
把 git 的端口号改成和代理一致 -
检查电脑内是否安装 go 环境和 Hugo,没有的话下载,Hugo 版本号要带 extended,否则后续安装主题时会报错;右键 shell 或 git bash 输入
hugo version
弹出版本号即成功安装;如果提示需要键入\hugo
才能使用命令,说明你没有把 hugo. Exe 添加到环境变量 -
备份需要保留的博客文件,包括 source 文件夹中所有博文、图片、音乐资源,以及你在新博客可能还会用到的 css 和 js 内容(或者直接将原来仓库里的内容克隆到本地)
-
在原来设置了远程仓库连接的文件夹中 (即,文件夹中有. Git 文件夹)清空本地仓库
rm -rf * .github .gitignore .nojekyll
,最好在这一步之前将所有源文件内容备份 -
提交删除
git add .
,确认操作git commit -m"清空hexo文件"
,推送到远程仓库git push origin master
- 如果操作的文件夹里没有. Git 文件夹,说明这个文件夹不是上传内容的本地仓库,会报错
- 如果不想这样做,或者推送远程仓库不成功,可以直接在网页 GitHub 上将 hexo 博客所在的仓库分支删除,再重新创建。(前提是它不是默认分支)
- 如果 hexo 原先的内容在默认分支,就重新创建一个分支,将它修改成默认分支。修改默认分支在 Setting 标签页,删除分支在 branch 按钮
- 如果 hugo 内容推送到的远程仓库分支不是默认分支,有可能其内容不显示
-
确认仓库已经清空,以下所有操作均在 git bash 中完成。
创建站点并部署
-
在创建的 Hugo 文件夹中使用
hugo new site .
创建一个新站点, -
克隆或下载一个 Hugo 主题,我使用的是 meme 主题,手动下载了安装包,解压后放在站点文件夹里的theme 中
-
按照 meme 说明文档所要求的,删除 Hugo 新建站点时生成的 toml 文件,将
themes/meme/config-examples/zh-cn/
中的config.toml
复制到博客根目录- 如果没有删掉就复制,会报错 failed to load modules 或 failed to trtansform "en/style/main-render. Sass"
-
使用
hugo new "posts/hello-world.md"
新建一个测试页面,使用hugo new "about/_index.md"
新建关于页面 -
键入
hugo serve
预览,注意,这一步只能在根目录完成,Hugo 会为你的博客生成一个 public 文件夹,存放真正展示给访客的 HTML 页面- 如果没有出现页面,是因为 md 文件头部分 draft 设置成了 true ,要么使用
hugo serve -D
预览,要么在 archetypes 文件夹中,将默认新建 md 文件头中的 draft 项改成 false 再重新新建 md 文件
- 如果没有出现页面,是因为 md 文件头部分 draft 设置成了 true ,要么使用
-
根据文档提示新建 tags 分类页面
hugo new tags/_index.md
和分类页面,此时页面没有内容,在 hello-world 文件头中的 tags 项写入['标签内容']
,这样就将文章打上了标签 -
确认博客可以正常渲染和跳转各个页面后,进入到 public 文件夹中
cd public
,新建本地仓库git init
,将本地仓库与远程仓库进行连接git remote add origin https://github.com/xxx/xxx.github.io.git
-
确保此时本地仓库所在的分支是 master
git checkout -M master
,如果不是,将其切换成 master -
将所有改动写入本地仓库
git add .
并确认git commit -m"新建Hugo博客"
-
推送 public 中的内容到远程仓库
git push -u origin master
快速部署
-
Hugo 博客和 Hexo 不同在于,Hexo 可以直接在预览后使用
hexo d
将新内容推送到仓库,Hugo 没有集成此命令,需要使用 git push 命令来推送,但是可以用 hugo 官方推荐的 GitHub Actions 流程简化 -
在根目录中的. Github\workflows 中新建 hugo. Yaml 并输入以下内容,其中 branches 和 env 的 hugo 版本根据自己的需求更改
# 用于构建和部署Hugo网站到GitHub Pages的示例工作流程
name: 发布Hugo网站到Pages
on:
# 在目标为默认分支的推送上运行
push:
branches:
- master #要推送的仓库分支
# 允许您手动从“Actions”标签运行此工作流程
workflow_dispatch:
# 设置GITHUB_TOKEN的权限,以允许部署到GitHub Pages
permissions:
contents: read
pages: write
id-token: write
# 仅允许一个并发部署,跳过在进行中的运行与最新排队的运行之间排队的运行。
# 但是,请不要取消进行中的运行,因为我们希望这些生产部署能够完成。
concurrency:
group: "pages"
cancel-in-progress: false
# 默认使用bash
defaults:
run:
shell: bash
jobs:
# 构建作业
build:
runs-on: ubuntu-latest
env:
HUGO_VERSION: 0.143.1 #Hugo版本
steps:
- name: 安装Hugo CLI
run: |
wget -O ${{ runner.temp }}/hugo.deb https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb \
&& sudo dpkg -i ${{ runner.temp }}/hugo.deb
- name: 安装Dart Sass
run: sudo snap install dart-sass
- name: 检出
uses: actions/checkout@v4
with:
submodules: recursive
fetch-depth: 0
- name: 设置Pages
id: pages
uses: actions/configure-pages@v3
- name: 安装Node.js依赖
run: "[[ -f package-lock.json || -f npm-shrinkwrap.json ]] && npm ci || true"
- name: 使用Hugo构建
env:
# 为了与Hugo模块的最大向后兼容性
HUGO_ENVIRONMENT: production
HUGO_ENV: production
run: |
hugo \
--gc \
--minify \
--baseURL "${{ steps.pages.outputs.base_url }}/"
- name: 上传构建产物
uses: actions/upload-pages-artifact@v2
with:
path: ./public
# 部署作业
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
needs: build
steps:
- name: 部署到GitHub Pages
id: deployment
uses: actions/deploy-pages@v2
在博客根目录中直接git bash后输入,没有搞懂,还是选择更改博客内容后在根目录预览git add . && git commit -m "更新" && git push
hugo serve
,使用脚本文件推送,本质上没有用到GitHub Actions ;其中脚本文件除了推送的三个命令外还有cd public
,这样就不需要点进public使用git bash了;脚本文件使用指令为./push.sh
最后查看 GitHub page 的托管网站是否已经更新为 hugo 的内容。
博客文件迁移
直接将所有原博客md文件复制到content\posts中即可,需要注意以下要点
- 如果使用了abbrlink,文件头部分会存在
abbrlink: 371d23cb
这样的项,需要用脚本将所有文件的这一项读取并新建url: posts/371d23cb
项,这样hugo才能读取并保证原来的url不变 - 在archetypes文件夹中默认页面写入
slug = '{{ substr (md5 (printf "%s%s" .Date (replace .TranslationBaseName "-" " " | title))) 4 8 }}'
,这样hugo新生成的文章才同样使用abbrlink
美化
以下所有内容都基于 meme 主题 进行更改前,将 meme 文件夹中 assets、layout、data、static、i 18 n 文件夹复制到根目录中,并且只在根目录中进行修改
博客内部美化
- 修改主页布局为 page,在 content 文件夹中新建_index. Md 文件作为首页,如果不想要显示标题,直接将文件头部分 title 内容留空
- 删除右上角菜单的图标:注释掉\layouts\partials 中的 menu. Html 文件中第 37、38 行内容
{{- $iconName := (string .Post) -}}
{{- partial "utils/icon.html" (dict "$" $ "name" $iconName "class" .Identifier) -}}
- 修改文章页面段间距:在\assets\scss\layout 中 post. Scss 中修改 .post 的内容
.post {
p {
margin: 1em 0;
}
- 其他美化内容在config.toml中修改即可
短代码和 css
主要从这位博主的博客里抄了一些来用,也从爱海的博客里 copy 了一些
图片轮播
新建\layouts\shortcodes\imgloop. Html
{{ if .Site.Params.enableimgloop }}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Swiper/3.4.2/css/swiper.min.css">
<!-- Swiper -->
<div class="swiper-container">
<div class="swiper-wrapper">
{{$itItems := split (.Get 0) ","}}
{{range $itItems }}
<div class="swiper-slide">
<img src="{{.}}" alt="">
</div>
{{end}}
</div>
<!-- Add Pagination -->
<div class="swiper-pagination"></div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Swiper/3.4.2/js/swiper.min.js"></script>
<!-- Initialize Swiper -->
<script>
var swiper = new Swiper('.swiper-container', {
pagination: '.swiper-pagination',
paginationClickable: true,
//自动调节高度
autoHeight: true,
//键盘左右方向键控制
keyboardControl : true,
//鼠标滑轮控制
mousewheelControl : true,
//自动切换
//autoplay : 5000,
//懒加载
lazyLoading : true,
lazyLoadingInPrevNext : true,
//无限循环
loop : true,
});
</script>
{{ end }}
在页面中用 {< imgloop "/images/1.jpg,/images/2.jpg,/images/3.jpg" >}
来使用(要用两个{}包裹此句内容,下同)
友链
新建\layouts\shortcodes\friend. Html
{{- if .IsNamedParams -}}
<div class="frienddiv">
<a target="_blank" href={{ .Get "url" }} title={{ .Get "name" }} class="friendurl">
<div class="frienddivleft">
<img class="myfriend" src={{ .Get "logo" }} />
</div>
<div class="frienddivright">
<span class="friendname">{{- .Get "name" -}}</span>
<span class="friendinfo">{{- .Get "word" -}}</span>
</div>
</a>
</div>
{{- end }}
在页面中用 {<friend name="" url="" logo=" " word="">}
来使用
Aplay音乐播放器
新建\layouts\shortcodes\music. Html
<h2>{{.Get 0}}</h2>
<audio controls autoplay loop preload="none" src="{{.Get 0}}">
<p>Your browser does not support the <code>audio</code> element.</p>
</audio>
然后在\layouts\partials\custom\head.html中插入
<!-- require APlayer -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.css">
<script src="https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.js"></script>
<!-- require MetingJS -->
<script src="https://cdn.jsdelivr.net/npm/meting@2/dist/Meting.min.js"></script>
使用以下代码在页面中插入播放器,参数见Aplay官方文档
<meting-js
name="song name"
artist=" "
url="/music/musci.mp3"
cover="/images/song_cover.png"
theme="#A52A2A"
mini="true">
</meting-js>
字数统计
在\layouts\partials\custom\footer.html中插入以下代码
{{$scratch := newScratch}}
{{ range (where .Site.RegularPages "Type" "posts") }}
{{$scratch.Add "total" .WordCount}}
{{ end }}
{{$var := $scratch.Get "total"}}
{{$var = div $var 100.0}}
{{$var = math.Ceil $var}}
{{$var = div $var 10.0}}
<footer>
<p>匣子里共有 {{$var}}k 字</p>
</footer>
用 Type 和 posts 两个参数筛选的页面是文章页面,使用"Params.tags"对标签内容相符的文章进行筛选但不知为何我筛选出来是空的
页面插入卡片格式
新建\layouts\shortcodes\card. Html
{{- $raw := (markdownify .Inner | chomp) -}} {{- $block := findRE
"(?is)^<(?:address|article|aside|blockquote|canvas|dd|div|dl|dt|fieldset|figcaption|figure|footer|form|h(?:1|2|3|4|5|6)|header|hgroup|hr|li|main|nav|noscript|ol|output|p|pre|section|table|tfoot|ul|video)\\b"
$raw 1 -}}
<div class="mycard">
<div class="content">{{- if or $block (not $raw) }}{{ $raw }}{{ else }} {{ $raw }} {{ end -}}</div>
</div>
在页面中用 {< card >}内容{< /card >}
来使用,内容中可以使用 html 和 md 语言
诗歌引用
新建\layouts\shortcodes\middle. Html
<div class="quote-center">
{{- $content := .Inner | markdownify -}}
{{- if not (strings.HasPrefix $content "<p>") }}
{{ printf `</p><p>%s</p>` $content | safeHTML }}
{{- else }}
{{- $content }}
{{- end -}}
</div>
在文本中用 {< middle >}诗歌{< /middle >}
使用,如果要换行,使用 <br>
配套使用的 css
其中,如果使用了卡片和诗句引用短代码必须写入相应样式,彩色文字用 <font class='colorfulfont'></font>
来使用;其他用 <div class='...'></div>
来使用
//彩色文字样式
.colorfulfont {
background: linear-gradient(to right, rgb(117, 9, 9), #6a6d83);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
// 卡片样式
.mycard {
padding: 10px 20px;
margin: 20px 0;
border-radius: 4px;
word-break: break-all;
background: transparent;
box-shadow: 0 6px 10px 0 alpha(var(--color-contrast-high), 0.15);
.content {
line-height: 30px;
}
}
//诗句引用样式
.quote-center {
background-color:transparent!important;
position: relative;
border-left: none;
padding-left: 0;
padding: 20px!important;
border-radius: 5px!important;
border-top: 0px solid var(--color-markdown-blockquote-border);
border-bottom: 0px solid var(--color-markdown-blockquote-border);
p {
text-align: center !important;
margin-top: 1.5em!important;
margin-bottom: 1.5em!important;
font-weight: lighter;
}
&::before {
position: absolute;
left: 0;
content: '– ‐‐——– ‐‐——';
font-size: 0.75em;
font-weight: lighter;
margin-top: -0.5em;
}
&::after {
position: absolute;
right: 0;
content: '– ‐‐——– ‐‐——';
font-size: 0.75em;
font-weight: lighter;
margin-top: -0.5em;
}
}
//自设定卡片式边缘
.circle-black {
padding: 40px 25px 50px;
border: solid 1px ;
margin-bottom: 12px;
display: flex;
flex-direction: column;
flex-wrap: nowrap;
justify-content: flex-start;
align-content: center;
}