使用了很久的 Volantis 换成了 Stellar。这两个主题都很棒!喜欢的话各位少侠可以试试!感谢开发这两个主题的各位佬!真的太厉害啦!膜拜~

一、Hexo 创建博客

本文基于 Github Pages 进行搭建。由于 Github 在国内的的现状并不大好,如果少侠想要自己博客访问速度更快,可以考虑使用 Gitee Pages,Gitee 需要实名认证以及手动更新部署,这点儿需要注意。

本文开始之前,默认少侠的系统已安装如下环境,并掌握这些工具基本使用:

本文难免有疏漏之处,如果少侠是第一次使用/听说,建议先通读一遍 Hexo 官方文档,不论是对于搭建博客还是更换主题配置亦或是后期解决问题等都有很大的帮助。

1. 创建新的博客

1
2
3
4
5
6
7
8
# 创建博客文件夹
mkdir myblog && cd myblog
# 全局安装 hexo
npm i -g hexo-cli
# 初始化博客目录
hexo init
# 安装一个插件,后面部署时需要使用(hexo d)
npm install hexo-deployer-git

TIP: hexo init 进行初始化的博客目录必须是一个空文件夹。

之后你会看到下面的目录结构:

1
2
3
4
5
6
7
8
9
|--.github
|--node_modules
|--scaffolds
|--source
|--themes
|--config.landscape.yml
|--_config.yml
|--package-lock.json
|--package.json

2. 创建 Github 仓库

Github Pages 中有相关说明:每个 GitHub 帐户和组织都有一个主站点和无限的项目站点。即 GitHub 支持用户创建静态的宣传网站,该站点使用固定的格式创建仓库:username.github.io

username 是 GitHub 的用户名。比如浪子的用户名就是 jhlzlove,那么仓库的名称就是 jhlzlove.github.io。少侠可以参照 Github Pages 中的方式创建(新手推荐),也可以按照下面的方式创建,效果都是一样的,但是前者更加简单。

无限的项目站点 本文没有讲解,熟悉了这个之后可以自行了解,也是非常简单的。

在 Github 上创建完 yourusername.github.io 仓库后再进行以下操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
cd myblog

git init
# 关联你的远程仓库
git add origin git@github.com:yourname.github.io.git

# 浪子喜欢放到 main 分支上
git checkout -b main

git add -A
git commit -m "first commit my blog"
# 推送到远程分支,并且建立分支间的追踪关系.
git push -u origin main

3. 更改配置文件并部署

修改 myblog/_config.yml 文件:

myblog/_config.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# URL
## Set your site url here. For example, if you use GitHub Page, set url as 'https://username.github.io/project'
url: http://yourname.github.io
permalink: :year/:month/:day/:title/
permalink_defaults:
pretty_urls:
trailing_index: true # Set to false to remove trailing 'index.html' from permalinks
trailing_html: true # Set to false to remove trailing '.html' from permalinks

...

deploy:
# 类型
type: git
# 部署分支名称,按照自己喜欢的起名就可以。这里写完还需要在 GitHub 上进行分支创建并配置
branch: pages
# 仓库,这里使用的 SSH 方式
repo: git@github.com:yourname/yourname.github.io.git
# 如果你看了 hexo 的文档,这里就很清楚啦,部署的时候会使用这个消息作为提交的信息
message: Automatic deploy by Github Action:{{ now('yyyy-MM-dd HH:mm:ss') }}

上面的配置更改完成以后,还需要在 Github 中配置一下,否则部署之后访问 https://yourname.github.io 是访问不到的。

等待部署成功,就可以访问 https://yourname.github.io 查看博客的效果啦!

1
2
3
4
5
6
7
# 先推送备份,可以跳过这步直接进行 部署
git add .
git commit -m "push config"
git push

# 部署(也可以直接使用 hexo s 本地预览)
hexo cl && hexo g && hexo d

二、Stellar 主题配置

上面部署使用的是 Hexo 的默认主题 landscape。Hexo 提供了上百种主题供用户选择,可以查看 Hexo 主题商店 进行选择,本文使用的是 Stellar 主题,再次感谢作者提供这么好看、好用的主题!

1. 安装 Stellar 主题

推荐使用 submodule 的方式安装,如果动手能力较强的少侠或者想要自定义的大佬可以进行 fork 后换成自己的 GitHub 地址,方便自己修改和更新。

1
2
3
cd myblog

git submodule add https://github.com/xaoxuu/hexo-theme-stellar.git themes/stellar

编辑 myblog/_config.yml 文件:

myblog/_config.yml
1
2
3
# 默认为 landscape
# 这里的名字是博客主题目录 myblog/themes/ 下的主题文件夹名称
theme: stellar

默认的主题配置文件为 _config.landscape.yml,修改该文件的名称为 _config.stellar.yml 并删除里面的所有内容。

主题配置文件形如 _config.xxxxx.yml,其中 xxxxx 对应主题文件夹的名称,里面的内容需要参考对应的主题文档进行修改。

2. Stellar 主题配置

Stellar 主题可以参考 Stellar 文档 进行配置,原作者大大写的很详细。但是第一次使用可能有些细节不懂,浪子也一样,过段时间回来再看就会恍然大悟!如果不会可以留言哦,相互学习一下!

本文的 stellar wiki 为基于 1.28+ 的配置方式。

2.1 Stellar 的 wiki 文档配置

Stellar 中最令浪子惊喜的地方就是这个了,可以让我把某一类的文章全部扔在这里。这里的配置可能对于新手有些难度,所以本文主要讲了 wiki 文档配置。浪子当时也反复弄了好久,在这里记录一下。哦,对了,要注意的是 Stellar 1.20 之前和之后的版本 wiki 文档的配置方式发生了较大的变化,可以查看作者的 Github Release 1.20 wiki 配置说明

wiki 同样支持 tags 分类,如果你需要分类的话可以参考浪子的分类方式:把 tags 的分类名称作为 source/wiki/ 下的目录名称,然后在每个 tags 里写具体的项目,这样统一分类,便于管理。Stellar 主题会根据 wiki 项目 id 自动归类所有的文章,无论该路径下嵌套了多少层目录:

浪子这里以 cloudservice 为例作为 wiki 项目 id,该项目的所有 md 文档都在 source/wiki/技术加油站/云原生与微服务/ 目录下。

1. 编写文档
source/wiki/技术加油站/云原生与微服务/path/xxxx.md
1
2
3
4
5
---
layout: wiki
wiki: cloudservice # wiki 项目 id,下面创建的 source/_data/wiki/ 中的 yml 文件名称必须与此相同
title: xxxx
---

path 可为任意文件夹,因为同一个项目中的文章也可以分类放置

2. 编写此项目 wiki 说明(配置) 创建 source/_data/wiki/cloudservice.yml 文件
source/_data/wiki/cloudservice.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# name title 为自定义文章名称
# name 和 title 的区别在于 name 是内容页面显示的名称,title 是在 wiki 列表中显示的名称
name: cloudservice
title: 云原生与微服务
description: 描述,wiki 列表中显示在 title 下方的简单文字描述
# 分类标签
tags: 技术加油站

# 不显示封面,默认显示:true
coverpage: false
cover: https://oss.muzing.top/image/Nginx_%E5%8F%8D%E5%90%91%E4%BB%A3%E7%90%86.png
# wiki 列表标题旁的 icon
icon: https://oss.muzing.top/image/Nginx_%E5%8F%8D%E5%90%91%E4%BB%A3%E7%90%86.png

# 搜索配置,在该 wiki 页中只能搜索指定路径的文章内容
search:
filter: /wiki/技术加油站/cloudservice/
placeholder: cloudservice 中搜索...

# 覆盖侧边栏
sidebar:
- toc
- timeline_stellar_releases
- related

# wiki 页分类目录
# stellar 主题会自动查找并显示该目录的所有文章
base_dir: /wiki/技术加油站/cloudservice/

# 如果文章需要分组,则按照此格式
toc:
'容器':
- index # 实际文章路径:/wiki/技术加油站/cloudservice/index.md
- path/Docker # 实际文章路径:/wiki/技术加油站/cloudservice/Docker.md

# 若无需分组按照以下格式
# toc:
# - index
# - path/Docker
# - otherDoc
3. 新建 `source/_data/wiki.yml` 文件添加以下内容(就是 wiki 项目 id)。如果这里不添加,则不会在 wiki 列表中展示
source/_data/wiki.yml
1
- cloudservice

完成之后重新部署即可,效果可以看浪子的 wiki 效果。想必有以上的示例就明白如何配置了,如果还不明白,建议再读一遍原作者的 文档系统使用说明

三、其它

1. 错误处理

如果遇到报错并且不知道错误原因的话,可以使用 hexo g --debug 命令查看 debug 输出信息。

2. 使用永久链接插件解决中文转义

如果我们写的文章标题是中文的话,那么在进行链接的分享时是会进行转义的,至于为什么要转义,请自行百度。我们可以安装一个插件,给链接 “化个美美的妆”,化妆后就是形如 https://xxx.xxx.com/posts/8ddf18fb.html 的漂亮女孩儿啦!

安装插件:

myblog/_config.yml 中找到对应 permalink 标签,进行修改即可:

myblog/_config.yml
1
2
3
4
5
# permalink: :year/:month/:day/:title/
permalink: p/:abbrlink/
abbrlink:
alg: crc32 #算法: crc16(default) and crc32
rep: hex #进制: dec(default) and hex

不同算法、进制生成的链接格式如下:

算法 进制 生成链接示例
crc16 hex https://yourname.github.io/p/66c8.html
crc16 dec https://yourname.github.io/p/65535.html
crc32 hex https://yourname.github.io/p/8ddf18fb.html
crc32 dec https://yourname.github.io/p/1690090958.html

3. 引入Mermaid流程图

Hexo 默认的 markdown 解析器不支持 Mermaid 流程图,需要安装插件来支持:

Stellar 主题的作者大大已经做了集成,使用此主题只需要安装后在主题配置文件中找到 mermaid 的 enable 项设置为 true,在需要渲染的文章的 front-matter 里加入 mermaid: true 即可。

如果使用的其它主题,可能需要自己做一些配置,具体的配置可以参考该插件的 官网说明。如果嫌弃配置麻烦或者实在不想配置,可以使用下面的方法。

另一种解决方案:hexo-filter-kroki,安装完成后,默认情况下,不需要进行任何配置,插件会将您的文本发送到 Kroki.io 进行渲染,并将 base64 编码的图像内联在 html 中。在插件作者的仓库中也有高级配置说明,可以自行查看配置。

1
2
# 懒人推荐
npm install --save hexo-filter-kroki

四、使用 Github Action 自动部署

使用自动部署只是省了三个命令 hexo cl && hexo g && hexo d,但是可以作为 CI 的入门案例,自己写着玩玩,你也可以借助 package.json 脚本命令和 npm 等包管理器,一个命令解决。有很多方式都可以实现,看各位少侠的喜好喽~

1. 配置不同仓库的 SSH 密钥

本文示例的 Github Action 为不同仓库之间的配置,部署的时候就像我们自己推送到 Github 平台类似,需要认证(permission)。为什么我要使用不同的仓库呢?因为 Github Pages 服务必须使用公开库(Public),但是我的源文件不想让其他人可见,因此我的 Hexo 博客是私有库,只有最终的 html 文件在 username.github.io 网站。

如果少侠的博客源文件和 Pages 网站都在一个仓库,属于不同分支,按照此种方法也可以,但是较为麻烦。后面浪子会介绍另一种方式,不需要配置 SSH 密钥,简单便捷。

1.1 创建新的 SSH 密钥:

ssh-keygen -t ed25519 -C 'xxx@xx.com' -f ~/.ssh/github_action_key,创建完成后会在 ~/.ssh/ 路径下生成两个文件:github_action_keygithub_action_key.pub

1.2 设置密钥

公钥配置在 Pages 服务仓库

yourname.github.io 仓库,依次点击 settings -> Deploy keys -> Add deploy key。该 key 的作用主要是验证用户是否有权限进行仓库的操作。

  1. title 随便填写;
  2. key 的值填写上面生成的 github_action_key.pub 的全部内容;
  3. Allow write access 选项打勾。
私钥配置在源文件仓库(私有仓库)

在另一个仓库中,依次点击 settings -> Secrets and Variables -> Action,新建一个 secret:

  1. Name 随便填写,后面编写 Action 脚本时需要用到;
  2. Value 填写 github_action_key 私钥的全部内容。

2. Action 脚本编写

Github Action 的脚本文件是在 .github/workflows/ 路径下,支持 yml 格式。脚本中我们还可以引用别人已经写好的脚本。

需要明确的是,如果你使用的 Hexo 主题中有 自定义标签,并且在 markdown 文件中有所使用的话,Action 自动部署的时候会发生解析错误,找不到自定义标签的解析内容进而无法正常使用 Action。所以,还记得本文开始的时候推荐使用 git submodule 的方式?

在 Hexo 博客仓库中使用 git submodule add origin https://github.com/username/xxxx.git themes/xxx 的方式去添加主题,然后在 yml 文件中 检出分支 时使用 submodules: true 选项开启子模块检出:

.github/workflows/deploy.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
name: Hexo Blog CI

# master branch on push, auto run
on:
push:
branches:
- main

jobs:
build:
runs-on: ubuntu-latest

steps:
# check it to your workflow can access it
# https://github.com/marketplace/actions/checkout
- name: Checkout Repository main branch
uses: actions/checkout@v4
with:
submodules: true # Checkout private submodules(themes or something else)
fetch-depth: 0

# from: https://github.com/actions/setup-node
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20

- name: Setup Hexo Dependencies
run: |
npm install && npm install hexo-deployer-git
npm install -g hexo-cli

- name: Setup Deploy Private Key
env:
HEXO_DEPLOY_PRIVATE_KEY: ${{ secrets.ACCESS_TOKEN }} # 仓库的私钥的 Name,需要改为自己的
run: |
mkdir -p ~/.ssh/
echo "$HEXO_DEPLOY_PRIVATE_KEY" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan github.com >> ~/.ssh/known_hosts

- name: Setup Git Infomation
run: |
git config --global user.name "github-action"
git config --global user.email "github-action@no-reply.com"

- name: Deploy Hexo
run: |
hexo clean
hexo generate
hexo deploy

博客源文件和 Pages 网站文件在相同仓库的不同分支的简单方式

如果少侠的 Hexo 博客源文件和 Pages 网站文件是在相同的仓库中,可以按照类似上面一样的方式配置,无非就是公钥、私钥都设置在同一个仓库中,同样是没有问题的,但是较为麻烦。

接下来介绍一种简单的方式,此方式 只适用于 md 源文件和 Pages 网站文件都在 同一个仓库,只是属于不同分支。如果使用过 vuepress、vitepress 等,那么此方式和它们一样。

Github Action 提供了 ${{ secrets.GITHUB_TOKEN }} 变量,该变量会在 workflows 结束后立即过期。该变量具有不同权限,可以在 yml 中修改整个工作流或单个作业的 GITHUB_TOKEN 权限。具体内容请看 官网说明

该方式无需配置 SSH 密钥,直接使用上面的变量即可,下面给一个脚本,少侠使用的时候修改部署的分支名称即可。如果需要指定其它变量,可以查看使用的脚本官网。

.github/workflows/deploy.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
name: Deploy Hexo Blog

# master branch on push, auto run
on:
push:
branches:
- main

jobs:
build:
runs-on: ubuntu-latest

steps:
# check it to your workflow can access it
- name: Checkout Repository main branch
uses: actions/checkout@v4
with:
submodules: true # Checkout private submodules(themes or something else)
fetch-depth: 0

# from: https://github.com/actions/setup-node
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20

# 生成文档
- name: Generator docs
run: |
npm i
npm install -g hexo-cli
hexo cl && hexo g
# 使用已有的 action 进行部署
# https://github.com/JamesIves/github-pages-deploy-action
- name: Deploy pages
uses: JamesIves/github-pages-deploy-action@v4
with:
# 使用 public 内的文件部署到 pages 分支
folder: public
# 部署分支
branch: pages
# 默认使用 secrets.GITHUB_TOKEN
# token: ${{ secrets.GITHUB_TOKEN }}

使用脚本之后,少侠只需写完文章后,把 md 源文件所在的仓库的内容推送到 Github 即可,等待一会儿再次访问 yourname.github.io,如果看到内容更新即代表成功。

使用 Action 之后你会发现一个新的问题:部署之后访问博客,所有文章的 发布时间更新时间 都是最近提交的时间,这就有问题了。分析原因也简单:Github Action 部署需要 clone 我们的库,clone 之后所有文件的日期都更新了,如果在 md 文件的 front-matter 中指定了 date 属性则正常,但是浪子之前所有的博客都没加!不过这个影响也不大。

之后在浪子所在的一个群里某位大佬推荐了一个插件:hexo-filter-date-from-git,试了试,果然好使!不过注意,使用该插件需要脚本必须设置 fetch-depth: 0 项检出所有的 git 日志,若此项不设置,该插件只能根据最新的 git log 获取提交时间进行覆写,那么这样你就会发现,和原来没有使用插件一样了。

1
2
3
cd myblog

npm install hexo-filter-date-from-git --save

五、Stellar 主题美化

引入一言小组件

source/_data/widgets.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
hitokoto:
layout: markdown
title: 一言
content: | # support markdown
<span class="hitokoto">一言加载中...</span>
<script>
document.addEventListener('DOMContentLoaded', async () => {
try {
const response = await fetch('https://v1.hitokoto.cn');
const data = await response.json();
// 获取页面上用于显示一言的元素
const dom = document.querySelector('.hitokoto');
// 设置一言内容
if (dom && typeof data.hitokoto === 'string') {
let res = data.from ?? false ? "—— 《" + data.from + "》":""
dom.innerText = data.hitokoto +" "+ res;
} else {
console.error('未能获取或解析一言数据,或者找不到目标 DOM 元素');
}
} catch (error) {
console.error('请求过程中发生错误:', error);
}
});
</script>

配置示例(在你需要显示的地方引入组件即可):

_config.stellar.yml
1
2
3
4
5
site_tree:
# -- 列表类页面 -- #
# 主页配置 引入 hitokoto 一言组件
home:
leftbar: hitokoto, recent

设置分类标签颜色

_config.stellar.yml
1
2
3
4
5
6
7
8
article:
...
# 添加分类的标签并设置对应的颜色
category_color:
'探索号': '#f44336'
'编程后花园': '#A505F0'
'技术加油站': '#c0ea66'
'人生图书馆': '#EDADFF'

页脚添加运行时间

_config.stellar.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
footer:
...
content: | # 支持 Markdown 格式
<uptime></uptime>
<script>
setInterval(() => {
let startDate = new Date("2023-10-01")
let now = new Date();
// 计算时间差(以毫秒为单位)
let differenceInMs = now.getTime() - startDate.getTime();
// 转换为天数、小时数、分钟数和秒数
let days = Math.floor(differenceInMs / (1000 * 60 * 60 * 24));
let hours = Math.floor((differenceInMs % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
let minutes = Math.floor((differenceInMs % (1000 * 60 * 60)) / (1000 * 60));
let seconds = Math.floor((differenceInMs % (1000 * 60)) / 1000);
let uptimeTags = Array.from(document.getElementsByTagName("uptime"));
uptimeTags.forEach(ele => { ele.textContent = `🌱 本站已活了 ${days} | ${hours} | ${minutes} | ${seconds} 🌱` });
}, 1000);
</script>

不过这样需要手动把 new Date() 的时间换成站点开张的时间


本站由 江湖浪子 使用 Stellar 1.29.1 主题创建。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。