Hexo静态博客指南:本站是如何诞生的(2021年版)

本文详细记录一下本站的建立过程,以便查阅。对于具体的细节则不会做过多解释,主要展示步骤。这一篇主要讲述准备工作、首次部署、自动部署、更换NexT主题以及后续维护的相关内容。本文是Hexo静态博客指南:本站是如何诞生的(上)(2020年版)Hexo静态博客指南:本站是如何诞生的(中)(2020年版)的更新版。

本文运行环境:

1
2
3
4
5
node: v16.13.0
npm: 8.1.4
hexo: 5.4.0
hexo-cli: 4.3.0
NexT: 8.8.1

准备工作

准备工作主要参考了Hexo官方文档

安装Git与Node.js

在Mac上最方便的方法当然是通过Homebrew

1
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

注意,可能在安装之前需要先安装Command Line Tools for Xcode。直接在终端输入xcode-select --install安装。

安装好Homebrew后,直接使用以下命令:

1
2
brew install git
brew install node

在安装以上两个依赖之前,可以先运行brew update来更新Homebrew。此外,还可以运行brew doctor检查一下有没有什么冲突,可以及时处理。也可以把以下语句加入你的.bash_profile或者.zshrc,取决于你使用的shell:

.bash_profile
1
export PATH="/usr/local/bin:$PATH"

安装好后,可以用以下命令查看是否安装成功,成功则会返回版本号:

1
2
git --version
npm -v

安装Hexo

直接使用npm安装:

1
npm install -g hexo-cli

查看一下hexo是否安装成功,会返回当前的hexo版本号:

1
hexo -v

注册GitHub并新建个人仓库

GitHub就不用多说了。注册完成后,新建公有仓库,名称为你的GitHub用户名.github.io,比如我的就叫做bambrow.github.io。这个仓库用来存放渲染好的页面。

此外,我们再新建一个私有仓库,用来存放源文件本身。仓库的名字任意取,我取的名字是blog

这两个仓库最好不要初始化任何东西,也就是README.gitignorelicense都不要。这样新建的仓库完全是空的。

设置Git与密钥文件

首先运行以下两句进行Git配置:

1
2
git config --global user.name "GitHub用户名"
git config --global user.email "GitHub注册邮箱"

其中把用户名和邮箱替换成你自己的。然后我们生成密钥文件:

1
ssh-keygen -t rsa -C "GitHub注册邮箱"

直接一路回车下去就好,结束后会在~/.ssh/文件夹里生成id_rsa私钥文件与id_rsa.pub公钥文件。我们读取一下公钥的内容并且手动拷贝:

1
cat ~/.ssh/id_rsa.pub

手动复制显示的内容。随后打开这个页面设置SSH Key。你也可以在GitHub主页点击你的右上角头像,选择Settings,然后选择SSH and GPG Keys找到这个界面。点击New SSH Key,标题可以随便写,内容就是你刚才复制的公钥内容,随后保存。

开始建站

博客初始化

首先选择一个你喜欢的地方作为你的博客根目录。我自己选择了与bambrow.github.io的同名目录。

1
mkdir ~/git/bambrow.github.io

随后按照官方教程,依次运行:

1
2
3
hexo init ~/git/bambrow.github.io
cd ~/git/bambrow.github.io
npm install

现在博客已经初始化完成了。使用以下命令:

1
hexo server

就可以在http://localhost:4000看到你的站点了。可以在终端里使用control+c关掉本地服务器。下面列举一些常用的命令,更多命令与参数可以参考这里

  • hexo clean 用于清除缓存与静态文件。
  • hexo new "文章标题" 用于新建文章。
  • hexo server 用于启动本地服务器查看渲染好的网页,可简写为hexo s
  • hexo generate 用于生成静态文件,可简写为hexo g
  • hexo deploy 用于部署网站,需要先设置好_config.yml,可简写为hexo d

设置_config.yml

首先,可以参考官方的设置页面,这里只涉及一些核心设置。

用你喜欢的编辑器打开根目录下的_config.yml。在Site下面你可以更改网页的标题、副标题、描述、作者、语言、时区等等。语言这里选择zh-CN。在URL下面可以把url改为你的GitHub Pages的URL,https://你的GitHub用户名.github.io。中间的大部分设置跳过,你也可以参照上面的网页进行修改。

最后,我们重点关注一下# Deployment。在这里,我们需要把它改为如下的样式:

_config.yml
1
2
3
4
deploy:
type: git
repo: 你的GitHub目录地址
branch: master

其中repo要根据自己的情况修改。你可以在GitHub主页点击你的头像,选择Your repositories,点击你的你的GitHub用户名.github.io仓库,点击Code按钮,然后点击Use SSH(如果目前显示为Clone with HTTPS),然后复制框中的内容到这里。

修改好后,保存文件。

首次部署

我们需要再安装一个依赖:

1
npm install hexo-deployer-git --save

随后一切就绪,依次运行:

1
2
3
hexo clean
hexo g
hexo d

然后你就可以在https://你的GitHub用户名.github.io看到渲染好的网页了。

设置自动部署

在这一步里我们不仅备份了博客的源文件,也实现了修改push到blog私有仓库后触发GitHub Actions完成自动部署。

将源文件备份至私有仓库

在终端,自己的GitHub用户名.github.io文件夹内,手动添加远程仓库:

1
2
git init
git remote add origin git@github.com:bambrow/blog.git

这里的远程仓库就是你的blog仓库。把上面的git@github.com:bambrow/blog.git修改成你自己的仓库地址。方法同样是在网页进入blog仓库,点击Code按钮,然后点击Use SSH(如果目前显示为Clone with HTTPS),然后复制框中的内容到这里。

随后我们编辑一下.gitignore文件。可以使用你喜欢的编辑器。一般来讲,.gitignore应该有如下内容:

.gitignore
1
2
3
4
5
6
7
.DS_Store
Thumbs.db
db.json
*.log
node_modules/
public/
.deploy*/

编辑好之后,先做:

1
git pull origin master

随后把所有应该备份的文件push到GitHub:

1
2
3
git add .
git commit -m "initial commit"
git push origin master

此时去GitHub上查看blog仓库,会发现内容已经更新。

设置GitHub Actions

请注意,在做这一步之前,请务必确认自己的blog仓库是私有仓库,如果不是,一定要在设置里将其设置为私有。

之前建立好的密钥文件,有公钥也有私钥。我们已经用过了公钥,这次使用私钥。首先读取其内容并手动拷贝:

1
cat ~/.ssh/id_rsa

手动复制全部内容。随后在网页上打开自己的blog仓库,点击Settings,再点击左侧的Secrets,随后新建。名称可以随意写,这里推荐HEXO_DEPLOY_KEY;内容则是刚才复制的私钥全部内容。随后点击添加。

随后,我们开始设置工作流。点击你的仓库标签下的Actions,选择新建New workflow。随后选择set up a workflow yourself,将main.yml的内容替换如下,你也可以自行修改:

.github/workflows/main.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
52
53
54
# 工作流名称
name: Hexo Blog Deploy

# 只在push到master分支的时候启动
on:
push:
branches:
- master

# 使用ubuntu虚拟机
jobs:
build:
runs-on: ubuntu-latest

# 工作流步骤
steps:
- name: Checkout repository master branch
uses: actions/checkout@master

# 安装Node.js
- name: Install node.js
uses: actions/setup-node@master
with:
node-version: "16.x"

# 安装Hexo
- name: Install hexo
run: |
npm install hexo-cli -g
npm install

# 设置SSH密钥,读取HEXO_DEPLOY_KEY
- name: Setup private key
env:
HEXO_DEPLOY_KEY: ${{ secrets.HEXO_DEPLOY_KEY }}
run: |
mkdir -p ~/.ssh/
echo "$HEXO_DEPLOY_KEY" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan github.com >> ~/.ssh/known_hosts

# 配置Git设置
- name: Setup git settings
run: |
git config --global user.name "GitHub用户名"
git config --global user.email "GitHub邮箱"
# 更改上面的用户名和邮箱

# 部署
- name: Deploy hexo
run: |
hexo clean
hexo generate
hexo deploy

随后点击Start commit结束设置。这样以后只要有新的改动被push到blog的主分支,就会触发这个工作流,将网页渲染出来,同时也会push到你的GitHub用户名.github.io这个仓库里。

安装Markdown语法扩展

Hexo原生的Markdown渲染插件支持的Markdown语法不够丰富,比如不支持GitHub Flavored MarkdownCommonMark、上标下标、脚注等等。因此,我们在写文章之前,可以把原生的插件hexo-renderer-marked改为hexo-renderer-markdown-it

首先,根据该插件的安装指南,运行以下命令:

1
2
npm uninstall hexo-renderer-marked
npm install hexo-renderer-markdown-it

随后在_config.yml里添加如下语句(可以添加在deploy前面):

_config.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
# Markdown-it config
## Docs: https://github.com/celsomiranda/hexo-renderer-markdown-it/wiki
markdown:
preset: 'default'
render:
html: true
xhtmlOut: false
langPrefix: 'language-'
breaks: true
linkify: true
typographer: true
quotes: '“”‘’'
enable_rules:
disable_rules:
plugins:
- markdown-it-abbr
- markdown-it-cjk-breaks
- markdown-it-emoji
- markdown-it-footnote
- markdown-it-ins
- markdown-it-mark
- markdown-it-sub
- markdown-it-sup
anchors:
level: 2
collisionSuffix: ''
permalink: false
permalinkClass: 'header-anchor'
permalinkSide: 'left'
permalinkSymbol: '¶'
case: 0
separator: '-'

随后你就可以使用扩展语法了。使用方法可以参看这里这里,尤其是后一个网页给出了很详细的例子。

如果你觉得脚注字体偏大,可以看我的Hexo NexT主题的字体更换,看完后就知道怎么修改了。我个人做了如下设置:

source/_data/styles.styl
1
2
3
.footnotes {
font-size: 75%;
}

因为我们上一步卸载了一个插件,所以也要改一下工作流文件,在安装Hexo那一步加一个步骤,卸载这个依赖。你可以在本地修改.github/workflows/main.yml的内容,也可以在GitHub的blog仓库,点击Actions,选择最近的一次部署,点击右侧的省略号中的View workflow file,然后点击右侧的铅笔按钮进行修改。将卸载依赖写在npm install那一行后面即可。如果你采用后者,在你将本地新的改动push到GitHub之前,要记得先做git pull,否则会报错显示远程仓库有新的改动。推荐在本地修改,一步到位。

.github/workflows/main.yml
1
2
3
4
run: |
npm install hexo-cli -g
npm install
+ npm uninstall hexo-renderer-marked

更换主题

我们这里选择的是NexT主题。Hexo支持许多主题,你也可以选择自己喜欢的主题。

安装NexT

NexT是非常流行的Hexo主题。根据这个网站,该项目几经易手,经历过很多不同的版本。我们现在当然是采用目前的最新版本。

首先我们运行hexo -vnpm -v查看一下HexoNode.js的版本,确保它们大于这个链接里所示的版本最低要求。

以下步骤主要参考了NexT官方文档。还是在博客的根目录里,运行如下命令(同时卸载默认主题,同样,卸载语句也应加入工作流):

1
2
npm install hexo-theme-next
npm uninstall hexo-theme-landscape # 加入工作流 Install hexo 部分

新主题就下载好了。下一步,我们打开站点配置文件_config.yml,找到theme那一行并改为theme: next,主题就更换完毕了。接下来需要拷贝主题的配置文件(以及删除旧主题的配置文件):

1
2
rm -f _config.landscape.yml
cp node_modules/hexo-theme-next/_config.yml _config.next.yml

你可以运行hexo clean; hexo g; hexo s来查看效果。

修改主题配置

主题配置的修改主要在_config.next.yml中进行。这里讲几个主要的配置。

主题样式与暗色模式

主题样式在# Schemes下面。一共有四种样式,分别是Muse,Mist,Pisces和Gemini。其中前两种是单栏样式,后两种是双栏样式,如果要更改,只需注释掉当前样式,再取消注释想要更改的样式即可。

在下方的Dark Mode选项里,你可以选择为网页开启暗色模式,只需要把false变成true即可。

菜单与侧边栏项目

# Menu Settings下面你可以选择开启菜单项目。它们都是默认关闭(被注释掉)的。需要哪一项,取消注释即可。

注意,除了homearchives,其他的页面需要手动添加。比如,你想要开启about页面,那么就要在Hexo根目录下运行:

1
hexo new page "about"

随后在source文件夹下面就会生成about目录,里面有index.md文件。你可以更改文件内的标题,随后在date行下面加一句:

source/about/index.md
1
+ type: "about"

如果需要还可以加上comments: false来为这个页面关闭评论(后文会讲到如何添加评论功能)。

就大功告成了。你可以随意编辑这个页面。你也可以自定义菜单项目,甚至可以嵌套项目,具体做法可以查看官方教程

这里举个简单的例子,假如我们要新建一个菜单项目叫做notes,首先在# Menu Settingsmenu下面新建一行:

_config.next.yml
1
2
3
4
5
6
7
8
9
10
menu:
home: / || fa fa-home
about: /about/ || fa fa-user
tags: /tags/ || fa fa-tags
categories: /categories/ || fa fa-th
archives: /archives/ || fa fa-archive
#schedule: /schedule/ || fa fa-calendar
#sitemap: /sitemap.xml || fa fa-sitemap
#commonweal: /404/ || fa fa-heartbeat
+ notes: /notes/ || fa fa-sticky-note

图标的代码可以去Font Awesome网页上查找。随后如前面的例子,手动添加页面即可。如要添加自定义菜单的中文翻译,需要新建source/_data/languages.yml文件,然后写入如下内容:

source/_data/languages.yml
1
2
3
zh-CN:
menu:
notes: 笔记

任何翻译都可以在这个文件里设置或覆盖。

此外,在# Sidebar Settings下面可以找到关于侧边栏的一些设置。除了它本身的一些参数,你还可以设置其中的一些内容,比如social下面可以开启你的社交网络账号与主页。另外,搜索back2top还可以让你把回到首页的按钮放在侧边栏,并开启阅读进度百分比功能。

网站图标与头像

网站图标可以在# Site Information Settingsfavicon下面找到。如果要更换,可以把图标放在source/images/目录里(如果没有这个目录就自己新建)。教程还推荐了这个网站来生成你自己的图标。

头像则在侧边栏设置的# Sidebar Avatar下面。你可以把头像放在source/uploads/目录里(如果没有这个目录就自己新建)。

知识共享许可协议设置

Creative Commons设置可以搜索creative_commons。它支持多种协议,默认是by-nc-sa。更多协议可以参考维基百科的解释

代码块样式

你可以在这里查看并选择你喜欢的样式,随后搜索codeblock修改。你还可以打开复制按钮,方便读者复制代码块里的内容。

阅读进度、书签与GitHub横幅

搜索reading_progress即可开启阅读进度功能。还可以在bookmark开启书签功能,读者可以选择点击书签图标来保存阅读进度,下次进入这篇文章时就可以继续阅读。

下面的github_banner可以让你开启GitHub横幅,它会在网页右上角显示一个小横幅,直通你的GitHub主页。

字体设置

# Font Settings可以更改字体设置,NexT允许你更改全局字体、网站标题字体、h1-h6标题字体,文章字体与代码字体。如果你的定制程度比较高,还是参看官方教程比较好。

设置中英文自动空格

这个功能已经内置在NexT主题中。在_config.next.yml中搜索并开启pangu即可。

增加第三方服务

同样,官方教程还是比较详细的,解释了很多第三方插件的用法,囊括了数学公式、评论系统、网站统计与分析、评分与分享小部件、搜索功能、即时聊天室等等。这里只讲一下我个人开启的服务。

LeanCloud阅读统计功能

这部分参考了这篇文章

注册LeanCloud时,建议注册国际版国内版要验证的东西比较多。然后新建一个应用,名字可以任意写。随后打开应用,点击存储条目下的结构化数据,然后点击创建Class,名称为Counter,其他保持默认。随后去设置里的应用Keys记下AppIDAppKey

打开_config.next.yml,搜索leancloud_visitors,将其打开,填写刚才的AppIDAppKeysecurity也设置为打开。随后的步骤比较多且复杂,请参考上面的文章,但是介于现在LeanCloud又有更新,所以做一点补充说明。

首先,上面的参考文章里,需要打开NexT主题配置文件的时候,我们统一打开_config.next.yml。其次,在博客配置文件_config.yml里,在theme:next后面(你也可以添加到别的位置)添加的内容是:

_config.yml
1
2
3
4
5
6
leancloud_counter_security:
enable_sync: true
app_id: 你的AppID
app_key: 你的AppKey
username: 你用"hexo lc-counter register"注册的用户名
password: 你用"hexo lc-counter register"注册的密码

记得在这之前要安装:

1
npm install hexo-leancloud-counter-security

然后,在配置deploy的时候,因为我们多加了一项,所以应该改为:

_config.yml
1
2
3
4
5
deploy:
- type: git
repo: 你的GitHub目录地址
branch: master
- type: leancloud_counter_security_sync

也就是每一个type前面都要加上-

随后,在设置Counter的权限时,我们在add_fieldcreate均选择指定用户,随后在用户名里输入你用hexo lc-counter register注册的用户名,它会自动找到对应的用户。在设置完后,两项都应该显示0 Role, 1 User。对于delete,选择指定用户留空即可,会显示显示0 Role, 0 User

请注意,当前版本的hexo-leancloud-counter-security插件存在bug,而且官方并未修复。这会导致GitHub Actions部署错误。如果你遇到了这个问题,请参考 Hexo静态博客升级指南 里的“远程部署”部分进行修改。

Valine评论系统

根据这条 Github Issue,Valine 评论系统在 NexT v8.1.0 后被移除。理由如下:

Valine 使用 Leancloud 作为后端,是一个深受静态博客用户喜爱的评论系统。然而 Valine 暴露出了一些令人担忧的问题:

  • NexT 团队曾多次收到关于 Valine 评论系统存在隐私数据泄露的反馈;
  • Valine 自 1.4 版本起不再开源,发布的打包版本中存在未告知用户的百度统计代码;
  • 2020 年 11 月下旬出现了针对 Valine 评论系统的网络攻击;
  • CVE-2021-34801

如需继续使用,需要额外安装插件。在项目根目录运行如下命令:

1
npm install next-theme/hexo-next-valine

Valine 即可正常运行。

在前一步的基础上,在_config.next.yml里的# Comments Settings下面添加如下条目(建议添加在Disqus前面):

_config.next.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Valine
# For more information: https://valine.js.org, https://github.com/xCss/Valine
valine:
enable: true
appId: # your leancloud application appid
appKey: # your leancloud application appkey
serverURLs: # When the custom domain name is enabled, fill it in here
placeholder: Just go go # comment box placeholder
avatar: mm # gravatar style
meta: [nick, mail, link] # Custom comment header
pageSize: 10 # pagination size
visitor: true # leancloud-counter-security is not supported for now. When visitor is set to be true, appid and appkey are recommended to be the same as leancloud_visitors' for counter compatibility. Article reading statistic https://valine.js.org/visitor.html
comment_count: true # If false, comment count will only be displayed in post page, not in home page
recordIP: false # Whether to record the commenter IP

随后填写appIdappKey即可。在这里,我们把visitor设置为true,随后把上一步的leancloud_visitors下的enable设置为false,因为两者之间有冲突。之后会考虑将评论系统从 Valine 迁出,会另外写文章说明。

不蒜子网页计数器功能

这个功能可以显示网站的浏览量和访客数。在_config.next.yml里找到busuanzi_count,将其打开,因为我们已经开启了LeanCloud的计数功能,所以将post_views关掉(否则文章内部的阅读次数会有异常),其他保持打开即可。

如果在本地测试,你会发现统计数据非常大,这是因为不蒜子通过域名统计,所以localhost:4000的数字会比较大,不必担心。

Local Search搜索功能

首先在根目录安装:

1
npm install hexo-generator-searchdb

随后,在博客配置文件_config.yml里加入:

_config.yml
1
2
3
4
5
search:
path: search.xml
field: post
format: html
limit: 10000

然后在_config.next.yml里打开local_search

Word Counter字数统计与阅读时长功能

首先在根目录安装:

1
npm install hexo-word-counter

随后,在博客配置文件_config.yml里加入:

_config.yml
1
2
3
4
5
6
7
8
9
symbols_count_time:
symbols: true
time: true
total_symbols: true
total_time: true
exclude_codeblock: false
awl: 4
wpm: 275
suffix: "mins."

阅读完本文后,请移步 Hexo静态博客指南:本站是如何诞生的(下) 进行进一步的部署。