Hexo 博客部署与重建记录
我已经记不得这是第几次重建博客了,虽然基于git仓库的备份,所有的md文件都还在,但是node_modules以及其他的环境配置会因为各种各样的原因损坏(换电脑,系统重装,迁移系统等),有必要重新梳理一下博客搭建的过程。
下面的内容主要是在Windows上和linux(WSL2)上的本地部署,以及在云服务器和Github Page的远程部署,并不涉及具体的Hexo主题以及配置细节。
生成与部署逻辑
Hexo是一个基于NodeJS的静态博客框架。首先梳理一下主要的工作逻辑:
- 在本地博客文件夹中,下载必要的Hexo组件并配置
- 在
source\_posts
目录中添加博客文件(markdown格式) - 生成并推送
- 执行
hexo generate
生成相应的静态网页,生成的静态网页及相关资源都会存放在public\
目录下 - 执行
hexo deploy
部署到远程仓库,实质上是将public\
目录下的所有内容打包复制到一个git本地仓库,然后提交到指定的远程仓库
- 执行
- 本地预览:执行
hexo server
启动本地预览,Hexo会在本地部署一个网站,通过http://localhost:4000访问。在本地启动期间,Hexo会持续监视博客文件变动并自动更新,无须重启服务器。但是对于配置文件的修改必须重启服务器才能生效。 - 清理本地缓存:执行
hexo clean
清理本地缓存(包括public\
和db.json文件),这可以有效避免一些错误。
日常写博客的流程:
- 启动本地预览:
hexo s
- 新建或修改博客文档
- 清理本地缓存:
hexo clean
- 生成并推送,完成博客的更新:
hexo g
,hexo d
由于Hexo生成的是静态网页,实际上我们只需要把public\
的所有内容复制到网站对应的目录下即可,然后配置Nginx确保文件夹可以被访问即可,通常这个复制过程使用git完成,但这并不是必须的。
本地搭建
准备工作
安装git,这没什么好说的。
安装nodejs(Latest LTS Version:
20.11.1),对于Windows很简单,对于Linux则略有不同,因为Ubuntu的apt提供的Nodejs版本太低,这里采用nvm给普通用户安装Nodejs,在普通用户家目录执行下面的命令安装nvm
1
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
这里给bash添加了一段配置,需要重新登录才能生效。
查看所有可供安装的node版本 1
nvm ls-remote
这里选择Latest LTS Version: 20.11.1安装 1
nvm install v20.11.1
查看本地已安装的node 1
nvm ls
使用指定版本的node 1
nvm use v20.11.1
安装pandoc(3.1.12.2),因为需要它来提供LaTeX渲染,在Windows上直接安装即可,Linux通过apt安装还是一样的问题——版本太低,安装过程如下:
首先通过pandoc的GitHub仓库下载pandoc-3.1.12.2-1-amd64.deb
文件并复制到家目录中,然后执行
1
sudo dpkg -i pandoc-3.1.12.2-1-amd64.deb
测试一下安装成功 1
pandoc -v
从零搭建
新建BlogBase/
文件夹,在其中本地安装hexo-cli
1 | npm i hexo-cli |
新建BlogBase/Blog
文件夹,在其中执行Hexo初始化(注意hexo必须在一个空文件夹里面进行初始化)
1
hexo init
由于hexo-cli不是全局安装的,存在找不到hexo命令的问题,对于Windows可以通过临时添加路径到PATH解决,在BlogBase目录下执行
1 $env:Path += ";$((Get-Item -Path .\node_modules\.bin -Force).FullName)"
对于Linux可以在Blog目录下添加hexo软链接 1
ln -s ~/blogbase/node_modules/.bin/hexo hexo
使用npm安装butterfly(butterfly主题不会放置在themes文件夹下)
1
npm install hexo-theme-butterfly
在_config.yml中切换主题,本地即可正常测试运行。
在基本功能测试完成之后,就可以安装插件并且进行相应配置,目前使用如下的插件:
- 本地搜索需要额外下载插件:hexo-generator-search
- 字数统计需要额外下载插件:hexo-wordcount
- 为了支持latex,首先需要root安装pandoc,然后卸载自带的hexo-renderer-marked,安装hexo-renderer-pandoc
- 部署的git插件默认也是没有的,需要安装hexo-deployer-git
- 一个似乎是支持置顶和隐藏的插件,卸载自带的hexo-generator-index,安装hexo-generator-index-custom
- 关于外链,安装hexo-filter-nofollow
- 关于sitemap,安装hexo-generator-sitemap
- 关于footer,安装hexo-butterfly-footer-beautify
如果npm下载的网络太慢,可以考虑换淘宝镜像源 1
npm config set registry https://registry.npmmirror.com
迁移搭建
如果已经有了Hexo博客的源代码仓库,那就更简单了:在BlogBase目录下安装hexo-cli之后,新建Blog文件夹并直接初始化Git仓库,然后拉取远程仓库的博客源代码仓库即可
1
2
3git init
git remote add origin <remote-url>
git pull origin main
然后自动下载依赖的插件(基于packages.json和packages-lock.json)
1
npm install
依赖顺利下载完成之后,就可以执行本地测试和进一步的部署了
1
hexo s
package.json
这里记录一下目前的package.json(2024年5月10日) 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{
"name": "hexo-site",
"version": "0.0.0",
"private": true,
"scripts": {
"build": "hexo generate",
"clean": "hexo clean",
"deploy": "hexo deploy",
"server": "hexo server"
},
"hexo": {
"version": "7.3.0"
},
"dependencies": {
"hexo": "^7.0.0",
"hexo-abbrlink": "^2.2.1",
"hexo-butterfly-footer-beautify": "^1.0.6",
"hexo-deployer-git": "^4.0.0",
"hexo-filter-nofollow": "^2.0.2",
"hexo-generator-archive": "^2.0.0",
"hexo-generator-category": "^2.0.0",
"hexo-generator-feed": "^3.0.0",
"hexo-generator-index-custom": "^1.0.1",
"hexo-generator-search": "^2.4.3",
"hexo-generator-sitemap": "^3.0.1",
"hexo-generator-tag": "^2.0.0",
"hexo-renderer-ejs": "^2.0.0",
"hexo-renderer-pandoc": "^0.4.0",
"hexo-renderer-stylus": "^3.0.0",
"hexo-server": "^3.0.0",
"hexo-theme-butterfly": "^4.13.0",
"hexo-theme-landscape": "^1.0.0",
"hexo-wordcount": "^6.0.1",
"with": "https://registry.npmmirror.com/with/-/with-7.0.2.tgz"
}
}
更新记录
2024年5月10日更新:添加了
hexo-abbrlink
插件,为博客生成唯一的哈希值链接,不再依赖于路径。2024年9月2日更新:添加了
hexo-generator-feed
插件,为博客提供RSS支持。
远程部署
部署插件源码分析
远程部署如果基于Git实现,那么通常使用hexo-deployer-git插件,这个插件不是默认的插件,需要手动安装。(还有一些非Git的方式,Hexo也提供了名为hexo-deployer-xxx的插件)
hexo-deployer-git插件需要我们在_config.yml中加入如下形式的配置,这里提供了两个Git仓库的例子
1
2
3
4
5
6
7deploy:
- type: git
repo: git@tc:blog.git
branch: main
- type: git
repo: git@github.com:<user>/<user>.github.io.git
branch: main
安装并配置好部署插件之后,hexo deploy
命令才会有具体的行为,实质等价于如下的命令:(分析depoly.js源码)
创建或清空
.deploy_git\
文件夹从
public\
文件夹复制所有内容到.deploy_git\
文件夹初始化 Git 仓库
1
git init
添加配置信息
1
2git config user.name "Your Name"
git config user.email "your.email@example.com"将所有文件添加到暂存区:
1
git add -A
提交
1
git commit -m "Site updated: {{ now('YYYY-MM-DD HH:mm:ss') }}"
推送到远程仓库
1
git push -u <remote_repo_url> HEAD:<branch> --force
部署插件其实就做了这些事情,至于通过Git仓库具体部署到了什么地方,与本地的行为无关。
由于我们已经完全拆解了部署插件的行为,完全可以考虑直接自己写一个脚本来代替它,例如
1
2
3
4
5
6
7
8
9
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
LOCAL_FOLDER_PATH="$SCRIPT_DIR/.deploy_git"
cd "$LOCAL_FOLDER_PATH"
# git remote add origin git@github.com:<user>/<user>.github.io.git
git push -u origin main
在Windows推送时,遇到了git换行符的问题,暂时把safecrlf从true改成warn,目前Windows中的.deploy_git的仓库级配置为
1
2 autocrlf = input
safecrlf = warn
云服务器配置
本地 hexo 推送到远程仓库 git@fenglielie.top:/home/git/blog.git,即通过 git 用户登陆云服务器的 ip。 这里需要先在云服务器中创建git用户,给 git 用户设置相应的 ssh 的密钥,并且在本地也设置相应的密钥,对于 git 用户通常还会禁用 shell 登陆。
具体的步骤如下:
- 第一步,部署到
/home/git/blog.git
文件夹,这是远程仓库的 git 数据库; - 第二步,调用
blog.git
里面的 hook(具体而言是hooks/post-receive
,也就是推送之后自动执行的动作),hook 的需要添加的内容如下,含义是将仓库的所有内容(也就是静态网站的所有内容,实际上就是public/
中的所有内容)在/home/open/blog
文件夹中展开1
git --work-tree=/home/open/blog --git-dir=/home/git/blog.git checkout -f
这里涉及到几个目录:
/home/git
以及它的子目录(git:git),存放当前云服务器上的所有远程仓库,包括/home/git/blog.git
博客仓库;/home/open
目录(root:root),存放了当前云服务器上所有的公开内容;/home/open/blog
目录(git:git),博客网站的主目录,里面存放了所有的网页文件。由于需要通过 git hook 进行读写操作,需要注意让git拥有权限。
注意,这里的
blog.git
仓库的大小可能随着推送次数增多而膨胀,可以过一段时间直接清空重置,但是要注意维护hooks/post-receive
。
可以考虑用另一个独立的git仓库备份所有博客及配置,单独调用git push
将
hexo 博客以及其它配置整体(不含node_modules/
)作为一个 git
仓库推送到远程仓库
git@fenglielie.top:blog_src.git
,这个远程仓库不需要设置
hook。
这里仅仅是把通过Hexo生成的静态网站所有内容放在了云服务器上的指定位置,为了让网站可以被外界通过网址成功访问,还需要考虑很多问题: 域名购买,服务器的公网ip与域名解析,SSL证书,腾讯云的防火墙+Linux系统防火墙,Nginx配置等。
Github Page配置
Github
Page是Github免费提供的,可以部署静态网站的服务,外界可以通过<user>.github.io
访问到网站。(当然也可以改成自定义域名,只需要改一下域名解析即可,这里暂不考虑)
Github
Page的实质和上面的云服务器配置是类似的,即本地将Git仓库推送到远程仓库,Github将远程仓库的内容放置在一个网站的根目录下,并且可以通过<user>.github.io
访问。
虽然原理类似,但是这个特殊仓库的配置,以及自动部署的过程还是值得注意的。
关于部署的内容,可以指定为仓库的某个分支,还可以进一步指定为某个文件夹。
有两种发布方式:
- (传统的)推送到特定分支时自动发布站点(使用默认的pages build and deployment工作流)
- (beta)编写 GitHub Actions 工作流来发布站点(使用自定义工作流)
前者直接把仓库指定分支的所有内容拷贝过去,用于部署网站;后者则基于Github Actions,即提供一个临时的虚拟机,可以在其中对仓库内容执行一些自定义的命令,然后将再部署网站。 目前选择前者即可。
补充:USTC HomePage
直接在Windows的文件浏览器路径栏输入ftp://home.ustc.edu.cn
,
输入登录名和密码,登录名是邮件帐号@
之前的部分,密码与邮件系统一样。
希望对外提供个人主页服务时,必须先创建子目录public_html/
,
这个目录里的所有文件均可以通过http://home.ustc.edu.cn/~YourID
来访问。在public_html/
中存放index.html
文件就可以提供默认首页,希望访问其它网页时,在URL中加上相对路径即可。