Hexo 静态博客框架 NexT 主题配置教程
写在前面
Hexo 是一款基于 Node.js 的静态博客框架。它通过解析 Markdown 文章生成静态网页。只需要将 Hexo 生成的文件托管到平台上,即可完成博客的部署。
Hexo 的主题包非常丰富,NexT 主题是其中的佼佼者,本文将使用该主题搭建博客,首先介绍如何从零开始搭建一个本地的 Hexo 运行环境,然后讲解如何将你的网站发布到云端。
相关链接
有精力更深入探索的同学可以自行阅读 Hexo 和 NexT 的官方文档,以获得更全面的了解。
Hexo 仓库:github.com/hexojs/hexo
Hexo 文档:hexo.io
NexT 仓库:github.com/next-theme/hexo-theme-next
NexT 文档:theme-next.js.org
推荐使用 Visual Studio Code 和它自带的 Terminal 来帮助我们管理博客。以获得最佳开发体验。
Visual Studio Code:code.visualstudio.com

本地 Hexo 配置
从安装环境开始
我们需要在本地安装 Node.js,用于提供 JavaScript 运行环境,并提供 npm 包管理器用于安装 Hexo 框架、NexT 主题和相关插件。
为了直接从 GitHub 下载主题,或者把博客部署到服务器或 GitHub,我们还需要安装 Git。
Node.js:nodejs.org
Git:git-scm.com
初始化站点文件夹
假定我们将要在 C:/Users/0xfaner/workspace/ 文件夹下创建一个名为 hexo-blog 的文件夹,作为博客项目的根目录。
首先安装 Hexo 的命令行界面,然后在自己指定的目录下初始化 Hexo,并进入站点文件夹中。1
2
3
4cd ~/workspace
npm install hexo-cli -g
hexo init hexo-blog
cd hexo-blog
认识 Hexo 命令
现在我们已经得到了一个初始的 Hexo 博客。让我们先认识一下 Hexo 的一些命令,再对博客进行个性化配置。
hexo clean: 清除生成的静态文件和缓存;hexo generate: 生成静态文件,可以简写为hexo g;hexo generate -d: 生成静态文件后将其部署,相当于hexo generate && hexo deploy,可以简写为hexo g -d;
hexo server: 启动网站服务,此时可以在浏览器中访问网站,可以简写为hexo s;hexo server --port [port]: 指定服务端口,可以简写为hexo s -p [port];hexo server --open: 启动服务后立即在本机默认浏览器中打开网站,可以简写为hexo s -o;
hexo deploy: 用于部署静态文件到远端服务器或平台,可以简写为hexo s -o;hexo deploy -g: 部署前生成静态文件,相当于hexo generate && hexo deploy,可以简写为hexo d -g。
大多数时候我们只需要用到两个组合命令。
preview: hexo server -open: 在 4000 端口启动网站服务并打开网页预览博客。publish: hexo clean && hexo generate && hexo deploy: 重新生成静态文件后部署到远端服务器或平台。
读者们可以尝试在本地运行一下 preview 命令,浏览器将自动打开 localhost,你将看到你的初始博客的样子。在后续的配置中,你可以随时运行该命令来查看你的修改所起的效果。
使用技巧
平时我们要经常组合使用这些命令,但是在命令行中敲写命令还是稍慢,我们可以利用 Visual Studio Code 帮助运行脚本,在站点文件夹中找到 package.json 文件,添加两条脚本:1
2
3
4
5
6
7
8"scripts": {
"build": "hexo generate",
"clean": "hexo clean",
"deploy": "hexo deploy",
"server": "hexo server",
"preview": "hexo server --open",
"publish": "hexo clean && hexo generate && hexo deploy"
}
然后我们可以在 Visual Studio Code 的 Explorer 框中找到 NPM scripts 栏(找不到的话可以在 Explorer 右键菜单中勾选让它显示),点击相应条目的 run 按钮即可快捷运行相应脚本。
修改站点配置文件
站点的配置文件为站点文件夹下的 _config.yml 文件。该文件描述了站点的源信息:标题、副标题、语言、时区等。我们可以通过修改该文件来完成对站点的配置。
.yml 文件对应了标记语言 YAML,用来表示序列化数据。在后面我们还会看到对应了标记语言 Json 的 .json 文件,功能和 YAML 接近,只是格式不同。
hexo server 运行中会检测博文的变动并进行动态更新,但是并不会检测配置文件的修改,你需要重新运行命令才能让更改生效。
安装 NexT 主题
在旧版 Hexo 中,应用主题的一个方式是从 GitHub 将主题仓库 Clone 到本地,放置在 Hexo 的 themes 文件夹下。这样一来整个主题对于用户来说就是透明的。我们可以随意修改主题文件夹内的任何文件来获得我们想要的效果,但这同时也带来了一些让人头疼的问题。
第一个问题是,NexT 主题更新非常频繁,如果我们想要让自己的主题保持最新,则需要不断与 GitHub 进行同步,我们不仅需要维护整个站点的仓库,还要单独维护主题仓库,定时从 GitHub 进行拉取。
第二个问题是,当我们对主题文件进行修改时,很容易让自己对 NexT 的修改与仓库的某处改动产生冲突,有时需要手动 Merge。
在新版 Hexo 中,有一个新方案解决了第一个问题,即使用包管理。我们可以使用包管理器来将主题作为一个 JavaScript 包进行安装,运行以下命令即可。参考 Installation | NexT。1
npm install hexo-theme-next
从设计上来说,我们不应该直接修改 node_modules 文件夹中的内容。因此在这种情况下我们很难自由对主题进行自定义。一个有经验的开发者应当尝试直接给开源社区提 PR,这样不仅实现了自己的需求,更可以回馈开源社区。这种做法也直接消除了第二个问题:作为开发者,合并冲突根本不算什么,对吧?
使用技巧
我们可以全局安装 npm-check-updates 包来帮助我们检查 package.json 中的依赖是否是最新版本。1
npm install npm-check-updates -g
检查更新时,我们只需要运行 ncu 命令即可,如果有待更新的包,则可以直接运行 ncu -u 命令来一键升级。
配置 NexT 主题
Hexo 的初始主题为 LandScape,我们对 _config.yml 进行修改,即可切换到 NexT 主题。1
2
3
4# Extensions
## Plugins: https://hexo.io/plugins/
## Themes: https://hexo.io/themes/
theme: next
读者们可以运行 preview 命令来查看 NexT 主题的样子。
与 Hexo 一样,NexT 主题的配置也依靠 _config.yml 文件。但是注意站点和主题的配置文件不是同一个文件,站点配置文件位于博客文件夹根目录下,而主题配置文件位于主题文件夹下。如果主题是通过 Git 安装的,那么主题配置文件位于 themes/next 文件夹中。如果是通过包管理安装的,那么主题配置文件位于 node_modules/hexo-theme-next 文件夹中。
通常情况下我们可以直接修改主题配置文件来配置主题,但是并不推荐这么做。推荐使用 Alternate Theme Config(备用主题配置)来配置 NexT。具体地,我们将主题配置文件复制到博客根目录,命名为 _config.next.yml,然后对该文件进行修改即可。参考 Configuration | NexT。1
2
3
4# Installed through npm
cp node_modules/hexo-theme-next/_config.yml _config.next.yml
# Installed through Git
cp themes/next/_config.yml _config.next.yml
配置插件
有些功能是 Hexo 默认关闭的,需要我们手动安装插件并启用,这里介绍一些常用的功能及其对应的插件。
数学公式
当我们想要在博文中嵌入数学公式时,启用 LaTeX 支持是一个明智的选择。不论是行内公式还是行间公式,都可以用一串简单的符号来表示。
Hexo 默认使用 hexo-renderer-marked 来进行渲染,但这个插件会导致 Markdown 标记和部分数学公式冲突,而 hexo-renderer-pandoc 则可以完美渲染。
若需要使用 hexo-renderer-pandoc,除了安装插件,还需要本地拥有 Pandoc 的环境。参考:Math Equations | NexT
1 | npm uninstall hexo-renderer-marked |
我们还需要在 _config.next.yml 文件中进行修改。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19# Math Formulas Render Support
# Warning: Please install / uninstall the relevant renderer according to the documentation.
# See: https://theme-next.js.org/docs/third-party-services/math-equations
# Server-side plugin: https://github.com/next-theme/hexo-filter-mathjax
math:
# Default (false) will load mathjax / katex script on demand.
# That is it only render those page which has `mathjax: true` in front-matter.
# If you set it to true, it will load mathjax / katex script EVERY PAGE.
every_page: true
mathjax:
enable: true
# Available values: none | ams | all
tags: all
katex:
enable: false
# See: https://github.com/KaTeX/KaTeX/tree/master/contrib/copy-tex
copy_tex: false
数据检索
专为 NexT 开发的数据检索插件,可以在侧边栏中看到一个检索按钮,点击即可弹出数据检索框,当你的博文内容较多时,启用搜索是个明智的选择。1
npm install hexo-generator-searchdb
我们还需要在 _config.next.yml 文件中进行修改。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18# ---------------------------------------------------------------
# Search Services
# See: https://theme-next.js.org/docs/third-party-services/search-services
# ---------------------------------------------------------------
# Local Search
# Dependencies: https://github.com/next-theme/hexo-generator-searchdb
local_search:
enable: true
# If auto, trigger search by changing input.
# If manual, trigger search by pressing enter key or search button.
trigger: auto
# Show top n results per article, show all results by setting to -1
top_n_per_article: -1
# Unescape html strings to the readable one.
unescape: true
# Preload the search data when the page loads.
preload: false
字数统计
专为 NexT 开发的字数统计插件,可以在每一篇文章的标题下显示字数,并在博客页脚显示整个博客的总字数。1
npm install hexo-word-counter
我们还需要在 _config.next.yml 文件中进行修改。1
2
3
4
5# Post wordcount display settings
# Dependencies: https://github.com/next-theme/hexo-word-counter
symbols_count_time:
separated_meta: true
item_text_total: true
远端部署
Hexo 官方提供的基于 Git 的部署插件,安装该插件后才可以使用 hexo deploy 命令。1
npm install hexo-deployer-git
我们还需要在 _config.yml 文件中进行修改。1
2
3
4
5
6
7# Deployment
## Docs: https://hexo.io/docs/one-command-deployment
deploy:
type: git
repo:
github: [email protected]:0xfaner/0xfaner.github.io.git
branch: master
如果是希望部署到服务器,那么我们必须使用该插件,但如果是希望部署到 GitHub,我们可以采用其他方案。
部署到 GitHub
GitHub 是世界上最大最先进的代码托管平台,当我们注册完账号,可以将自己的代码托管在 GitHub 中。同时 GitHub 提供了 GitHub Pages 的服务,它是一个静态站点托管服务,直接从 GitHub 上的存储库中获取 HTML、CSS 和 JavaScript 文件,并生成网站。
有两种方案进行博客的部署:
第一种:将站点源文件保存在本地,利用
hexo-deployer-git插件将博客部署到 GitHub Pages。第二种:将站点源文件保存在 GitHub,利用 GitHub Action,每次源文件仓库更新时自动部署到 GitHub Pages。
第一种方案较为常用,但第二种方案更为优秀。让我们细数第二种方案有哪些优点:
- 所有的文件都在 GitHub 有备份,数据更安全;
- 版本管理工具 Git 可以让站点源文件的变化清晰可见可溯源;
- 当我们配好博客设置并部署到 GitHub 后即可抛弃本地环境,添加博文可以直接在 GitHub 网站中完成,实现在线写作。
本文将介绍第二种方案。
配置本地 Git
首先配置本地的 Git 的用户名和邮箱。1
2git config --global user.name "0xfaner"
git config --global user.email "[email protected]"
然后生成密钥。1
ssh-keygen -t rsa -b 4096 -C "[email protected]"
生成过程中会需要我们输入三次信息,分别是需要保存密钥的位置,密钥的密码和重复密钥的密码,我们无需理会,全部回车跳过即可。密钥的位置默认保存在 ~\.ssh\ 文件夹中,其中私钥是 id_rsa 文件,公钥是 id_rsa.pub 文件。
创建 GitHub 账户
我们需要在 GitHub 注册一个账号,并在本地安装 Git 来将本地生成的静态文件部署到 GitHub Pages。
创建 GitHub 仓库
我们先在 GitHub 中创建两个仓库:
- 第一个名为
0xfaner.github.io:用作 GitHub Pages 的仓库。注意开头必须为自己 GitHub 账号的username而不是nickname。 - 第二个名为
hexo-blog:站点源文件的仓库。当然这个仓库的名字你可以自由发挥。
添加 SSH key
创建完仓库后,我们要让本地的 Git 获得操作仓库的权限。复制公钥的内容,加入到 GitHub 账号的 SSH Key 中。
使用以下命令即可快捷复制公钥内容到剪贴板。访问网页 github.com/settings/ssh/new 即可快捷为 GitHub 账户添加 SSH 密钥,将公钥的内容粘贴到 Key 框中,Title 可以随意命名,点击 Add SSH key 即可完成 SSH 密钥的添加。1
cat ~/.ssh/id_rsa.pub | clip
获取 Personal access token
为了让 GitHub Action 有权限向你的仓库 push 静态文件,我们需要创建一个 Personal access tokens(简称 Pat)。访问网页 github.com/settings/tokens/new 以进行创建。
其中 Note 可以随意填写,Expiration 可以设置为无限,但是为了安全起见,也可以设置为一个有限的期限。不过你要记得在它过期以前及时更新。权限部分只要勾上 repo 的权限即可。点击创建以后,你会获得一个以 ghp_ 开头的字符串,这就是你的 Pat,将它保存好。
设置 Actions secret
为了让你的 GitHub Action 能够获取到 Pat,同时又不把它泄露出去,你需要在你站点源文件仓库的设置页面中找到 Secrets 选项的 Actions 子选项,将你的 Pat 加入到里面。
填写时需要键入一个键值对,键可以随意起名,我使用的是 HEXO_CI_TOKEN,值即为你的 Pat。在下面的 GitHub Action 配置文件中,我们会通过 ${{secrets.HEXO_CI_TOKEN}} 来获取到你的 Pat。
修改 GitHub Action 配置文件
我们需要在 Hexo 根目录下创建 .github/workflows 文件夹,该文件夹下的 .yml 将被视为 GitHub Action 的配置文件,文件名可以自定义,本文采用 deploy.yml。
我们在 .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
31name: GitHub Pages CI/CD Action
on:
push:
branches:
- master
jobs:
build_and_deploy_job:
runs-on: ubuntu-latest
name: Build and deploy job
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install dependencies
run: |
sudo apt install -y pandoc
npm install
- name: Build Site
run: |
npm run build
- name: Deploy to github pages
working-directory: public
run: |
git init
git add .
git -c user.name='0xfaner' -c user.email='[email protected]' commit -m 'site update'
git remote add origin https://${{secrets.HEXO_CI_TOKEN}}@github.com/0xfaner/0xfaner.github.io.git
git push origin master -f -q
其中包括四个步骤:
准备环境:使用 Ubuntu 环境,加入 Git 和 Node.js 的支持;
Install Dependencies:安装 NPM 依赖,Pandoc 是数学公式插件的要求;Build Hexo Site: 执行 NPM 脚本build,生成静态文件;Deploy To GitHub Pages: 用 Git 将静态文件部署到 GitHub Pages。
这个 GitHub Action 将在你向站点源文件仓库 Push 代码时触发,它会自动创建环境、安装依赖、生成静态文件并部署到 GitHub。
收尾
现在让我们将站点源代码项目 Push 到 GitHub 中去,GitHub Action 将会自动运行。1
2
3
4git add .
git commit -m "first commit"
git remote add origin [email protected]:0xfaner/hexo-blog.git
git push -u origin master
在仓库的 Action 标签页可以看到 GitHub Action 运行时的详细信息。不出意外的话,你的博客会在几分钟内准备好,接下来可以开始你的写作了。
部署到远程服务器
从安装环境开始
如果我们希望将博客部署到远程服务器,那么我们就没有 GitHub Pages 和 GitHub Actions 可用了。
服务器中需要安装 Git 和 Nginx,分别用于接收静态文件,和建立网站服务,本文中服务器系统为 Debian。
配置本地 Hexo
我们需要安装对应的插件。可以参考前文的远程部署
配置本地 Git
我们需要在本地配好 Git 公钥私钥和用户名密码。可以参考前文的配置本地 Git
配置服务器 Git
首先安装 Git,然后查看 Git 是否安装完成。1
2sudo apt install git -y
git --version
出于安全考虑,我们新建一个名为 git 的用户,专门用于接收静态文件,然后切换到 git 用户。1
2
3useradd git
passwd git
su git
然后我们分别配置 Git 仓库的路径和静态文件的路径。Git 仓库目录在 /home/git/repos/blog.git ,静态文件部署在 /home/git/projects/blog。1
2
3
4cd /home/git/
mkdir -p projects/blog
mkdir repos && cd repos
git init --bare blog.git
我们需要配置 Git,利用 post-receive 实现自动化部署。1
2cd blog.git/hooks
vim post-receive
输入内容如下(不了解文本编辑器 Vim 操作的用户需要自行了解一下)。1
2
git --work-tree=/home/git/projects/blog --git-dir=/home/git/repos/blog.git checkout -f
然后配置可执行权限。1
2
3chmod +x post-receive
exit
chown -R git:git /home/git/repos/blog.git
然后我们测试一下仓库是否成功配置,在本地运行命令尝试将远端仓库 Clone 下来。1
git clone [email protected]:/home/git/repos/blog.git
如果能够把空仓库拉下来就说明配置完成。
然后我们建立 SSH 信任关系:
ssh-copy-id 命令为 Git Bash 自带。
1 | ssh-copy-id -i ~/.ssh/id_rsa.pub [email protected] |
如果不需要密码而成功登陆了,那么说明配置完成,运行命令 logout 即可退出登录。
安全起见,修改 /etc/passwd 文件,让 git 用户使用 Git Shell,这样它就只能使用 git clone 与 git push 等命令。1
2- git:x:1000:1000::/home/git:/bin/bash
+ git:x:1000:1000::/home/git:/usr/bin/git-shell
配置 Nginx
首先使用包管理安装 Nginx,然后查看 Nginx 是否安装完成。1
2sudo apt install nginx -y
nginx -v
安装完成后,启动 Nginx。1
sudo nginx
然后访问自己服务器的 IP 或域名来看看效果,如果无法访问,那么需要检查下服务器防火墙以及云服务器商的安全组策略。
修改 Nginx 的配置文件 nginx.conf,一般目录为 /etc/nginx/nginx.conf。1
sudo vim /etc/nginx/nginx.conf
如果目录位置不对,那么寻找一下 Nginx 的安装位置。1
whereis nginx
根据显示的目录找一下。
将其中的 user 从默认的 nginx 改为 git 或 root 以确保访问权限,防止出现 403 Forbidden 的无权限错误。
同时将根目录修改为静态文件所在的目录。1
2
3
4
5
6
7
8
9
10
11user git;
# ...
http {
# ...
server {
# ...
root /home/git/projects/blog;
# ...
}
# ...
}
开启 HTTPS 与 301 跳转
首先需要获取一份证书,可以使用 Let’s Encrypt 的免费证书或在阿里云等服务商处代为申请。
因为是纯静态博客,所以也不需要用 Certbot 等工具进行一键 HTTPS 配置,直接在 Nginx 里面加载证书就行。
首先将证书传输到服务器中,包括 .pem 和 .key 两个文件。然后将 nginx.conf 文件中的 HTTPS 部分取消注释,修改根目录,并配置证书路径。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22user git;
# ...
http {
# ...
server {
# ...
root /home/git/projects/blog;
if ($scheme = http) {
return 301 https://$host$request_uri;
}
# ...
}
# ...
server {
# ...
root /home/git/projects/blog;
ssl_certificate "new_path";
ssl_certificate_key "new_path";
# ...
}
# ...
}
修改完成后,重启 Nginx 即可。1
nginx -s reload
收尾
现在让我们在站点源代码执行命令,把静态文件发布到远程仓库吧。1
npm run publish
不出意外的话,你的博客会在几分钟内准备好,接下来可以开始你的写作了。
后记
废了不少时间重建博客重写博文,希望以后可以不用再折腾这个博客了(哭