搭建自己的静态博客并自动部署
1. 概述
本文讲解本博客的搭建方式
部件 | 作用 |
---|---|
Hexo | 把.md文章转换为页面,并且快速部署到平台 |
GitHub Pages | 提供从GitHub仓库创建网站的服务 |
GitHub Actions | GitHub提供的免费持续集成服务 |
Hexo + Github Pages
先从简单的讲起,看图:
简而言之:
- Hexo是一个博客框架,存放在你的电脑上,能把你的markdown文章转换成网站源码,并存入一个git仓库
- Github Pages是GitHub提供的免费静态网站服务,能让你展示文档。你只需要把网站源码存入一个repository,并且启用这个服务,GitHub就会帮你建一个静态网站,分配一个网址。别人从这个网址就能看到你的博客了。
- Hexo能一键把本地的网站源码推送到GitHub,让GitHub自动将其部署为Pages
GitHub Actions
前面的方法,网站所有的资源都存在本地,除了markdown文章和图片这种资源文件以外,网站的美化主题、配置等也存在本地。
这会产生几个问题:
数据容易丢失,一旦硬盘损坏,你的博客就灰飞烟灭了
只能在一台电脑上写文章,多台电脑之间hexo文件夹不好同步
网站的配置文件修改,没有历史记录追踪
由于网站的美化主题本身就是Github上的项目,每次要手动更新,很麻烦
每次写完文章,都要用hexo命令生成网站,还要用hexo命令部署网站,重复操作
所以,最好把hexo文件夹本身也当作Git项目,并放在GitHub托管。并且,还要把hexo部署的操作给自动化,让我们每次写完markdown文章,一 Push 就能自动部署页面。
这就要用到GitHub Actions,它是GitHub提供的持续集成(Continuous integration, CI)服务。这里不详述CI/CD的概念,你只需要知道,GitHub提供的这个服务,可以让你的仓库在特定条件下(例如push时),触发对应的动作(Actions)。
所谓的Actions,可以认为就是一条一条的Linux命令(也可以是Windows CMD命令)或者脚本,并且GitHub给你一个虚拟服务器去自动执行这一条一条的命令,这个虚拟服务器具有2核CPU,7GB内存,14GB硬盘。
你可以写自己的Actions,也可以用别人的Actions。Github提供了一个Action商店。
最终的效果应该如下图:
配置完成后的效果:
- 写完文章后,直接本地hexo仓库
commit
,然后push
- GitHub上的hexo仓库由
push
触发Actions,自动在虚拟服务器中生成网站源码,然后部署到网站仓库中 - 网站仓库(xxxx.github.io)更新时,自动更新Github Pages
- hexo的美化主题,作为hexo的git submodule,每次push时自动checkout最新分支
2. 搭建步骤
一些简单的步骤就只简略提一下。
2.1. 在GitHub创建仓库并启用Pages
- 注册一个GitHub账号
- 在GitHub创建两个仓库
<site_name>.github.io
和my-hexo
前者是GitHub Pages仓库,命名必须以github.io
结尾,后者是hexo仓库,可随意取名。
两个仓库都留空,不创建任何文件。 - 然后设置Pages,在
<site_name>.github.io
仓库中:
在仓库的Settings中,选择Pages,下方选择哪个分支的哪个目录被识别为网站的根目录。
GitHub现在的主分支是
main
而不是master
了,我是自己创建了一个master
分支,因为我本地的git默认主分支还是master。
2.2. 本地部署hexo
安装软件
首先安装依赖,需要安装的软件:
- Git (git-scm.com):版本管理
- Node.js:hexo所需的平台
Windows用户安装时,一定要勾选
Add to PATH
选项
然后安装hexo
npm install -g hexo-cli # 全局安装 |
关于Node.js和hexo的版本依赖关系,请参考:文档 | Hexo
初始化hexo
找个喜欢的地方创建一个文件夹用于存放hexo项目,例如my-hexo
。
进入这个仓库,然后进行hexo初始化
# 新建文件夹 |
注意:
- hexo初始化要求文件夹为空,因此必须先初始化hexo,再初始化git。否则
.git/
的存在将导致hexo无法初始化hexo init
时,产生了文件package.json
,里面记录了hexo所依赖的npm包的具体来源和版本号npm install
时,就根据package.json
记录的内容进行了包的安装。包的具体安装情况记录在package-lock.json
中
安装完毕后,目录结构应该如下
. |
初始化git并传到远程仓库
如果你从没用过git,需要配置本地的git用户和邮箱:
>$ git config --global user.name <用户名>
>$ git config --global user.email <邮箱>这个用户名和邮箱只是本地提交代码时记录修改人是谁,并非是要登录什么网站
还是在这个目录,进行Git仓库初始化
git init |
本文不解释git及其相关概念,后续使用git命令时,即使是复制,也务必明白你在做什么
另外,记得确认仓库中的
.gitignore
文件,它是hexo init <文件夹>
时生成的,其内容包括:
.DS_Store
Thumbs.db
db.json
*.log
node_modules/ # 安装的npm包
public/ # 生成的静态网站源码目录
.deploy*/ # xxxx.github.io仓库
_multiconfig.yml 这是让git不要去追踪一些自动生成的内容,这些内容与文章、站点配置无关。
然后再commit
:
$ git add . |
还记得前面在GitHub创建的my-hexo
仓库还是空的吗,现在需要把本地my-hexo
仓库绑定到GitHub仓库。
$ git remote add origin https://github.com/<用户名>/<仓库名>.git |
本地预览hexo网站页面
依次输入以下命令
$ hexo clean # 清理hexo缓存 |
终端中会打印本地网站的地址,Ctrl+鼠标左键点击访问即可:
可以看到默认页面即为成功,首页的唯一一篇文章是hexo自带的source/_post/hello-world.md
.
终端按Ctrl + C停止本地服务器
2.3. 配置hexo
安装主题
hexo有很多美化主题,可以在Themes | Hexo找到喜欢的主题,也可以在GitHub上搜索其他主题。我选择的主题是Butterfly - A Simple and Card UI Design theme for Hexo。主题除了美化外,往往还提供许多其他功能的配置。
主题放在themes文件夹下。不论安装什么主题,一定要注意:
- 虽然主题的官方教程一般都是让用
git clone
到themes文件夹下,但是我们的hexo文件夹已经是一个git仓库了,所以要以git submodule
的形式安装; themes
下的主题文件夹必须以<主题名>
来命名,而不是GitHub仓库的名称,如hexo-theme-<主题名>
。- 很多主题的官方说明会要求安装其他的npm包。使用
npm
安装这些包时,一定要带--save
选项。这样这些包才会被记录到package.json
中,这样我们以后push时,GitHub Actions上面的虚拟服务器才会帮我们完整的安装这些依赖。 - 主题本身的配置文件在
themes/<主题名>/_config.yml
中,但这个文件是被主题仓库管理的,不会被hexo仓库管理,无法推送到GitHub。而且主题仓库更新后我们修改的配置也会丢失。所以我们应当在hexo根目录下创建_config.<主题名>.yml
文件,并把主题中的配置文件拷贝进去。这样配置文件就会被hexo仓库管理。(但是原来主题文件夹里的_config.yml也不要删除)
下面是我安装butterfly的步骤:
- 把butterfly作为git submodule安装到hexo中
git submodule add -b master https://github.com/jerryc127/hexo-theme-butterfly.git ./themes/butterfly |
注意:
git submodule add
时,一定要指定主题的文件夹名称,将其命名为主题的名称,此处为themes/butterfly
。若不这样做,将会变成其GitHub仓库的名称,如hexo-theme-butterfly
,这样是不行的。
- 安装渲染器
根据butterfly的官方文档,需要安装渲染器。其他主题可能需要其他渲染器。
npm install hexo-renderer-pug hexo-renderer-stylus --save |
一定要带
--save
- 拷贝主题配置文件
把themes/<主题名>/_config.yml
配置拷到hexo根目录下
cp themes/butterfly/_config.yml ./_config.butterfly.yml |
- 应用主题
修改hexo配置文件,my-hexo
根目录下的_config.yml
,找到theme
项并修改:
theme: butterfly |
yml格式的
:
后面一定要有一个空格
- 查看效果
hexo clean |
- 其他修改
根据主题的官方说明,进行其他的自定义配置。所有的修改都在my-hexo根目录下_config.<主题名>.yml
中修改。
themes/<主题名>/_config.yml
虽然不生效,但是也不能删除。
配置hexo
hexo本身的配置,需要修改my-hexo
根目录下的_config.yml
文件。可以修改站点名称、作者等,具体可以参考官方文档:配置 | Hexo。
这里提一些与Github Pages还有markdown文章插入相关的配置。
网站url与root
目前,GitHub Pages提供的网站url为:
https://<用户名>.github.io/<仓库名>/
例如:
https://jayant-tang.github.io/jayant97.github.io/
所以,要配置hexo的目录:
url: https://jayant-tang.github.io/jayant97.github.io |
不同环境,访问资源的根目录是不同的。hexo的所有资源文件都应该放在
<hexo文件夹>/source
下,生成网页时,会自动拷贝到网页的根目录下。 例如,有一张图片资源的路径是:
<hexo文件夹>/source/foo/bar/image.png
:
- 对于你的markdown文章,可以设置根目录为
<hexo文件夹>/source
- 对于网站,刚才已经配置了根目录为
/jayant97.github.io/
只要设置好根目录,markdown和网页就可以使用相同的路径来访问到相同的资源了,如
/foo/bar/image.png
。
hexo的部署方式介绍
通常情况下,hexo的部署流程是这样的:
hexo g
,生成网页源码,并存储在/public
文件夹中hexo d
,把public同步到本地git仓库,然后推送到github仓库。
先安装git部署的插件:
npm install hexo-deployer-git --save |
然后需要给hexo配置github仓库的路径和权限,打开hexo配置文件:
deploy: |
选项 | 说明 |
---|---|
type | 部署类型,可以设置多个要部署的目标 |
branch | 分支名称 |
repo | 仓库名称,这里有ssh和https两种方式。使用ssh方式。 |
GitHub认证方式:
- https方式,任何人可以随便clone,但是push时需要在弹窗中输入账号密码,认证身份;
- ssh方式,需要ssh key,公钥放在GitGub,私钥自己持有。只要持有私钥就可以用ssh访问GitHub仓库,纯命令行操作,不会弹窗。
因为后面要用GitHub Actions在虚拟服务器里自动部署,所以需要用ssh的方式。
ssh密钥对的生成
然后需要生成两对ssh key,第一对用于电脑和GitHub之间的认证,第二对用于GitHub my-hexo仓库 和GitHub xxxx.github.io仓库之间的认证。
生成key:
$ ssh-keygen -t ed25519 -C "your_email@example.com" -f ~/.ssh/github_ed25519 |
-t
:选择加密算法,ed25519比较安全
-C
: 密钥的备注说明文字。Github要求这里要填上git config时配置的邮箱,同时也必须是GitHub中已经配置的认证邮箱。
-f
:生成的私钥文件名
执行完毕后,~/.ssh
下应该有4个新文件,其中带有.pub
后缀的是公钥,不带的是私钥:
~/.ssh |
GitHub ssh key设置
配置你的电脑ssh访问GitHub的权限。GitHub点击右上角头像-Settings,然后点击New SSH key:
然后,把github_ed25519.pub
的内容粘贴进去,其他都不用填,确认即可:
cat ~/.ssh/ed25519.pub |
测试:
$ ssh -T git@github.com |
有以上输出说明权限配置成功。
配置主题
根据你所使用的主题的官方文档来配置。建议把后面的其他部署都完成后,再研究主题的配置。
2.4. 从电脑部署hexo
前面的步骤都完成后,可以执行:
hexo d |
这时,hexo应该已经可以把网站配置到xxxx.github.io
上了,过一会从网页端就可以看到网站页面了。
网页端的入口:
Pages仓库右边:
然后点击View deployment
2.5. GitHub Actions自动部署
pages仓库添加公钥
我们需要设置my-hexo
仓库访问xxxx.github.io
仓库的权限,前者持有私钥,后者持有公钥。然后才能在push完my-hexo
仓库之后,让my-hexo
仓库的Actions自动部署博客到Pages仓库。
首先进入xxxx.github.io
仓库页面,找到Settings - Deploy Keys,然后点击Add deploy key:
把hexo_ed25519.pub
的内容粘贴进去:
cat ~/.ssh/hexo_ed25519.pub |
Title填写HEXO_DEPLOY_PUB
hexo仓库添加私钥
然后进入my-hexo
仓库,找到Settings - Secrets - Actions,然后点击New repository secret.
把私钥hexo_ed25519
中的内容粘贴进去:
cat ~/.ssh/hexo_ed25519 |
注意,Name要记住,后面需要用到。我这里配置的是HEXO_DEPLOY_PRI
.
编写Actions
在本地my-hexo文件夹中,创建一个文件.github/workflows/deploy.yml
,填入以下内容:
name: CI |
内容修改:
修改环境变量,改成你自己的用户名(GIT_USER)、邮箱(GIT_EMAIL)、pages仓库、pages分支
修改node_version: [xxxx],填上你电脑本地安装的Nodejs的版本
# 查看本地Node.js版本
node -v修改时区,如果在中国就不用改了
内容解释:
- 在hexo仓库的master分支收到push时,触发job
- 在Ubuntu环境中,checkout本仓库的最新内容,并且同时自动获取各个submodle的仓库。这里的
actions/checkout@v3
是Actions商店提供的,我们只需要用with
传参数进去就行了。商店页面Checkout · Actions · GitHub Marketplace。- checkout pages仓库,并把它放到.deploy_git路径中
- 安装指定版本的Node.js
- 配置环境变量:添加私钥、配置git用户和邮箱。注意,这里的私钥的名称就是
${{secrets.HEXO_DEPLOY_PRI}}
,与前面配置的HEXO_DEPLOY_PRI
一致。- 根据package.json的内容安装npm包
- 部署hexo博客
其他说明:
- 我没有使用商店中别人写的自动部署hexo的Actions,因为他们很久没更新了,使用的Node.js版本比较低,也没法通过传参的方式修改其内部使用的Node.js版本。
提交修改
从一开始到现在,已经修改了不少内容了,将其commit然后push
git add . |
add之前一定要注意检查.gitignore,是否已经让git忽略了
db.json
,node_modules/
,public/
。
push之后,在Github Actions页面应该已经可以看到流程了:
你的每次push,都会触发actions。绿色勾说明整个流程没有出现错误(指Ubuntu linux命令没有出现执行错误的)。如果执行失败,会出现红色叉,你可以点进去看详细的执行记录。
Actions执行完毕后,应该已经部署到Pages仓库了,这里也可以看到网站部署的记录:
绿色说明部署成功,网站已经可以访问了。
3. 编写并发布文章
3.1. 文章的存储与格式
所有要显示的markdown文章都存放在source/_posts/
目录下,不展示的文章(草稿)都放在source/_drafts
目录下。
新建文章:
hexo new [layout] <title> |
layout: markdown的布局(或者说模板),布局存放在
scaffolds/
目录下,默认有三种布局:
- post.md: 文章模板
- draft.md:草稿模板
- page.md:页面模板
title:文章的标题,直接写标题即可,不需要写.md。但是最好不要有空格等特殊字符!!!
以上命令,会在source/_posts/
目录下自动创建一个新的<title>.md
文件,并且把模板内容拷贝过去。由于模板中有date
参数,这时会自动记录当前的电脑本地时间作为这篇文章的创建时间,记录在Front-Matter中。
3.2. Front-Matter
Front-Matter是markdown文件最上方以两行---
分隔的区域,里面需要填写yml格式的文章配置,例如:
--- |
在Typora编辑器中,直接在文章开头输入---
并回车,就可以创建这个区域:
对于某些主题来说,有些选项是必选的,具体要看对应主题的说明文档。比如,我使用的butterfly主题,就可以配置:
title:文章标题
date:文章创建日期
cover:文章封面图
tags:文章标签
categories:文章目录
……
tags和categories的区别:
tags是无顺序的,categories是一个递归层级。设计好的tags和categories能让读者很方便的从主页索引到对应的文章。
这里,我们也可以体会到前面模板的意义:可以在模板里填好Front Matter,这样每次hexo就会自动帮我们生成了。
3.3. Typora在文章中插图的问题
方案一:云端图床
图片全部放在云端图床,markdown和Pages都通过URL查看图片。具体的方式,本文不介绍,可以去网上查阅。
方案二:图片放在本地
假设我们在markdown中展示一张图片,其路径为source/imgs/foo/bar/image.png
。
hexo生成网站后,网页会根据 ${root}/imgs/foo/bar/image.png
来找这张图片,即是说,source文件夹放的内容,在网页端就是根目录下的内容。
在2.3 配置hexo中,我们已经配置了root为
<仓库名>
了。
下面要解决的是,如何在markdown文章和网页中,能用同样的路径来访问图片资源。这样本地写文章时和网页端就都可以预览了,而且从markdown转换成html时,路径也是可用的。
解决方式就是根目录,由于hexo的根目录前面已经设置过了,我们只需要设置markdown编辑器的根目录就好。设置完毕后,而这就都可以通过/imgs/foo/bar/image.png
来访问同一张图片了。
(1)设置markdown文章访问图片时的根目录
我使用的Markdown编辑器是Typora,Typora支持针对每一篇文章单独设置根目录。
直接在Front-Matter中填入以下内容即可:
typora-root-url: ./.. |
由于文章的路径是
source/_post
,所以./..
就是source
了。
你可以把这一行配置直接写进scaffolds/post.md
中,这样下次模板就自动帮你填了。
以上设置,直接从菜单栏设置是一样的,Typora会自动帮你写这一行:
(2)设置Typora粘贴图片时的行为
直接在Front-Matter中写入:
typora-copy-images-to: ../../source/imgs/${filename}.assets/ |
这个效果和下图中的偏好设置是一样的,但是不要去偏好设置里去配置,因为那是全局的配置:
只需要在 Front-Matter 中写就行,不要去偏好设置里设置成上图的样子!!!
(3)检查效果
在Front-Matter中填入以上配置之后,每次粘贴图片到typora时,就会自动帮你把图片拷贝到source/imgs/<文章名>.assets/
文件夹中。
我们可以粘贴一张图片到typora中,检查图片位置:
然后,检查markdown访问图片的路径,查看markdown源码:
可以看到,路径名直接是从/imgs
开始的,这说明根目录已经是source
了。
以上配置全部写在Front-Matter中,把这两行配置写入
scaffolds/post.md
的Front-Matter中,这样模板就创建好了。这些配置就只对hexo中的markdown有影响,对你平时用typora写其他文章没有任何影响。
3.4. Typora中的html标签插图
如果你在Typora中右键点击一张图片,然后进行缩放,它就会从Markdown语法的图片:
![图片名称](图片路径) |
变成html格式的img标签,比如缩小到50%:
<img src="图片路径" alt="图片名称" style="zoom: 50%;" /> |
hexo在把.md
文章转换成html的时候,会自动根据我们设置的根目录来替换markdown格式图片的路径。
以本博客为例,![测试图片](/imgs/image.png)
会被转换成/jayant97.github.io/imgs/image.png
。
但是,如果.md
文章里的图片本来就是html格式的标签,hexo不会对其进行任何转换。这就导致,在网站上,图片的路径还是/imgs/image.png
,所以网站上就找不到图片了。
为了解决这个问题,网上解法很多。但我想了想,还是用Linux的sed命令来对文本进行替换,毕竟我并不懂JavaScripts。
sed -i 's#<img src="/jayant97.github.io/imgs/#<img src="/<仓库名>/imgs/#g' ./source/_posts/*.md |
以上三个命令会把<img src="/jayant97.github.io/imgs/
和<img src="/jayant97.github.io/imgs/
和<img src="/jayant97.github.io/imgs/
都替换成 <img src="/<仓库名>/imgs/
。
默认情况下,html标签中的写法:
./imgs
和imgs
是一样的,在网页端会被当作/<文章名>/imgs
。
/imgs
不会被转换,在网页端还是/imgs
在网页上,以上两种方式都访问不到图片,只有
/jayant97.github.io/imgs
才能访问到图片。因为所有静态资源都在source
文件夹下,而source
中的内容会被拷贝到<site_name>/xxxx.github.io/
中。
把这些命令加到GitHub Actions中,这样我们本地用typora的时候还是能看到图片,push到远程的时候网页也能看到图片。
首先在GitHub Actions的.yml文件中增加一个环境变量,方便后面更改:
然后,在hexo部署的步骤之前,加入sed命令:
- name: Sed img label |
这样云端部署的时候就会自动帮你替换路径了。
但是,本地
hexo s --debug
去查看网页的时候,由于没有Actions帮你转换,图片还是看不了的。这个问题倒没什么影响。
3.5. Typora云端和本地图片互转
如果你有一篇文章,以前所有的图片是放在云端的,现在想放在本地。可以批量操作:
只要文章已经写好了Front-Matter,那么整个复制过程会从你设置的图片根目录,来自动设置图片的路径。
同理,也可以批量把本地图片上传到云端(需要提前设置好上传方式),文章内所有的图片路径都会自动更新。
3.6. 文章的发布
文章写好以后,可以hexo s --debug
在本地查看一下。也可以hexo d
直接从本地发布。但是既然我们已经搭建好CI系统,可以直接add,commit然后push,后面的事情就交给GitHub Actions完成了。
Github Actions会在虚拟服务器上,根据我们写好的yml,自动执行hexo g
然后hexo d
,这样网站就重新部署好了。
但是这又会产生新问题:我们每次发布新文章,所有旧的文章都会被重新部署一遍,导致整个网站所有文章的更新日期都变成一样的了:
4. 网站的其他设置
基本概念
博客除了文章外,还有页面。页面的模板就是scaffolds/post.md
。可以有时间线、标签、目录等页面,页面也存放在source
目录下。
在_config.yml
中,配置了这些页面的目录:
基本上所有的配置你都可以在配置 | Hexo 和你所用的主题的官方文档中找到。
文章的永久链接(Permalinks)
hexo默认的文章URL格式是/年/月/日/文章标题
,如果你的文章标题有中文,这个URL就会巨长无比:
我的方案是改成用文章标题+日期的hash值去命名url,这样更简洁。
打开站点配置_config.yml
,修改:
permalink: :year/:month/:hash/ |
这样,文章的URL就会变成:
这样URL就比较短了。
文章的更新日期
文章具有创建日期(date)和更新日期(updated)。默认情况下,更新日期使用的是操作系统中记录的文件最后修改日期。
但是我们利用Github Actions部署时,
其他注意事项
- 所有文章标题、文件名、目录名都不要有空格等特殊字符!!!(可以有减号
-
) - 本博客使用了Gitalk作为评论系统,把页面仓库的Github Issue变成一个评论区。会有一些API key之类的东西,明文配置在hexo仓库中,所以我把hexo仓库的权限设为私有了
- Front-Matter是yml格式,冒号
:
后面一定要加一个空格,不然识别不了。