hexo + icarus主题个人博客搭建记录

hexo + icarus主题个人博客搭建记录

该怎么去描述写博客这件事?从功利的角度来看待,它能让简历与面试加分,能靠流量增加收入,不过都略显粗俗;从学习的角度来看待,输出自己的知识与思想,梳理总结凝练共享予他人,活脱脱的费曼学习法无疑了;从记录的角度来看待,这无不是汇聚毕生所学与所思的藏宝地。

hexo 的原理大概就是解析像我们写的 markdown 这样的文档,将解析后的数据集中管理,具体这些数据如何展示到网页上,就是主题去做的事情了,hexo 会拉取主题模板,将数据按照主题设计的样式渲染成一个个的网页,之后启动一个 http 服务器,便可以通过浏览器查看博客内容了。

环境准备

hexo 的运行只需要 nodejs 环境,对操作系统没有要求,在 Windows Linux MacOS 上均可运行。首先,到 nodejs 官网下载比较稳定版本的安装包并完成安装,nodejs 安装完成后会包含它的一个包管理工具 npmnpm 默认的包下载地址对国内用户访问下载速度不快,这里推荐 nrm 去切换国内下载地址进行加速,具体操作如下:

1
2
3
npm install -g nrm yarn	    # yarn 是可替代 npm 的包管理器
nrm ls # 查看可配置的远程链接
nrm use taobao # 使用淘宝链接,可以根据情况选择其他链接

之后,直接通过 npm 安装 hexo 的命令行工具 hexo-cli

1
npm install -g hexo-cli

安装完成后便可以在命令行里使用 hexo 相关命令进行博客的构建、配置、部署等操作了。

hexo站点构建

准备一个文件夹用于放置博客站点文件,然后在该文件夹中初始化一个 hexo 站点,操作命令如下:

1
2
3
mkdir blog
cd blog
hexo init

运行 hexo init 命令会去 github 拉取一个基本站点的模版以及一个默认主题到当前目录中,后续将以该模版作为基础进行改造。初始化完成后便可以通过命令 hexo server 去启动,然后打开浏览器访问 http://localhost:4000 便能看见一个博客网站的呈现了。

更换主题

默认的 hexo 主题较为简陋且不太美观,所以需要重新配置一个主题。网络上关于 hexo 的主题有很多,可以在 hexo 官方的Themes | 主题 中找到适合自己审美及实用需求的。我比较中意的两款主题分别是 Butterfly - A Simple and Card UI Design theme for HexoIcarus 这两个,最终选择了更为简洁的 icarus 。切换到 icarus 主题比较简单,可以直接使用 npm 安装该主题,之后使用 hexo 的配置命令即可完成切换:

1
2
npm install hexo-theme-icarus
hexo config theme icarus

切换完主题一般还不能使用,需要安装主题引用到的 npm 包,安装完主题所依赖的包后,尝试 hexo server 启动服务可能会报错,提示我们需要安装一些包的指定版本,那直接复制它提示的命令到命令行中执行安装即可,安装完应该就能正常启动了,命令如下:

1
2
3
4
yarn install    # 安装主题的依赖包
hexo server # 可能会报错
yarn add bulma-stylus@0.8.0 hexo-pagination@^2.0.0 hexo-renderer-inferno@^0.1.3
hexo s -p 8020 # 启动服务,指定端口为8020

hexo 的子命令一般都可用简写,像 server -> s,可通过 -p 选项指定服务监听的端口,然后浏览器打开http://localhost:8020 就能看到心仪的主题啦!

主题配置

每个人的博客总是不一样的,这些不一样的信息就配置到配置文件中,_config.ymlhexo 站点的配置文件,主要用于站点相关的配置;_config.icarus.ymlicarus 主题相关的配置,你有什么个性化的需求就通过这个文件去配置了;博客网站除了首页、分类、关于等这类的页面外就是最重要的文章的页面了,如果对文章页面有什么个性需求也可在 _config.post.yml 做配置。具体配置就是打开配置文件,根据注释等提示进行相应的配置即可,不用全配,配自己需要的即可。配置文件是 yaml 的格式(了解一下yaml格式)。详细可参考各自主题的配置教程,Icarus点这里

hexo 解析 markdown 文件中的外部静态文件链接时默认只支持绝对路径的方式,这对于文章中需要添加图片时就需要以 source 文件夹为根目录设置图片路径,好在 hexo 也提供了可用的相对路径的方式,不过相对路径的方式需要在文章的同级目录下创建一个文字同名的文件夹,这样文章才能以当前路径的方式引用同名文件夹下的静态资源文件,具体配置就是将 _config.yml 中的如下两项设置为 true 。 还需要注意的是,这一设定不支持 font-matter

1
2
post_asset_folder: true
relative_link: true

懂网页编程的话,可以对主题进行进一步的魔改。这里我参考了两位大佬的文章做了一定的改动:

这里贴出链接以示感谢,想要参考我这个主题魔改后源码与详细配置的话,请移步 gitee

我做的改动主要就是拉取 Alpha Lxy 的改动源码,除了 source/img 目录外基本都做了替换。source/img 目录下的一些logo,favicon,头像等文件都替换为自己的。然后对标签颜色和目录的滚动条做了一点源码的改动。由于我特别中意暗黑模式,所以参考了iMaeGoo 的改动源码增加了暗黑模式,将他主题源码中 source/css 下的 imaegoo.styl night.styl 文件拷贝自己相同的目录下并引入到 style.styl 文件中,然后拷贝暗黑模式切换的 night.js 文件到 source/js 中,因为懒,不想去找 night.js 的加载位置,night.js 是一个自执行函数,所以直接简单粗暴的将代码拷贝到同级目录下的其他 js 文件中。之后在 layout/common/navbar.js 组件中添加切换的图标,标签的 id 属性参考 night.js 设定。然后博客中用到的 gitalk 的评论组件,在暗黑模式下显示不太协调,这也直接将样式改动到了 night.styl 中。

由于主题的样式混合两个主题的样式,存在一定的冲突,导致页面看上去比例观感不太好,所以将 imaegoo.js 里除 tablet 外的其他屏幕适配都删除,重命名文件为 ereel.styl。由于导航栏在向下滚动的时候会移除画面外,移动端就会出现在看文章到中间及后面的时候切换不了暗黑模式及查看目录,所以针对移动端做了一点样式的调整,让屏幕滚动的时候导航栏的链接栏能吸附在屏幕顶部。在暗黑模式下,当代码块里代码长度过长,默认的滚动条观感与暗黑模式冲突,同样在 night.js 中对进度条做一下定制。

最终改动的文件 diff 如下:

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
55
56
57
58
59
60
61
62
63
64
65
66
/* ereel.styl */
*** 1,23 ****
screen-tablet = 769px
- screen-desktop = 1088px
- screen-widescreen = 1280px
- screen-fullhd = 1472px
- screen-onek = 1700px
primary-color = #5d93db
primary-color-hover = #71a1e0
primary-color-active = #4382d6
primary-color-light = rgba(93, 147, 219, 0.8)
link-color = rgb(68,155,255)

- @media screen and (min-width: screen-onek)
- .container
- max-width: 1600px
- width: 1600px
- .column.is-3-widescreen
- width: 22%
- .column.is-6-widescreen
- width: 56%
-
// Background image
body
background-color: transparent
--- 1,10 ----
***************
*** 31,40 ****
left: 0
opacity: 0.01
transition: opacity 1s
- background: url("https://api.btstu.cn/sjbz/?lx=dongman&format=images&method=pc") center 0 no-repeat
background-size: cover
- @media screen and (max-width: screen-tablet - 1)
- background-image: url("https://api.btstu.cn/sjbz/?lx=dongman&format=images&method=mobile")
body.ready:before
opacity: 1

--- 18,24 ----
***************
*** 53,62 ****
&:hover
color: white
background-color: primary-color
- @media screen and (min-width: screen-desktop)
- .navbar-menu
- .navbar-start
- margin-left: 2em
@media screen and (max-width: screen-tablet - 1)
.navbar-menu
flex-direction: column
--- 37,42 ----
***************
*** 68,73 ****
--- 48,58 ----
padding: .5rem
.navbar-end
padding-bottom: .5rem
+ @media screen and (max-width: screen-tablet - 1)
+ .navbar-main
+ position: sticky;
+ top: -5.3rem;
+ opacity: 1;

// Card fixes
.card
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
/* night.styl */
*** 60,66 ****
background-color: dark-primary-color
.navbar,
.card
- background-color: rgba(40,44,52,0.5)
backdrop-filter: none
-webkit-backdrop-filter: none
.card
--- 60,66 ----
background-color: dark-primary-color
.navbar,
.card
+ background-color: rgba(40,44,52,1)
backdrop-filter: none
-webkit-backdrop-filter: none
.card
***************
*** 269,274 ****
--- 269,291 ----
code
color: rgb(203,186,125)
background-color: dark-primary-color
+ .gt-container .gt-header-textarea
+ background-color: #373d48 !important
+ .gt-container .gt-comment-admin .gt-comment-content
+ background-color: #373d48 !important
+ .gt-container .gt-comment-admin .gt-comment-content p
+ color: #c0c0c0
+ .gt-container .gt-btn-preview
+ background-color: dark-primary-color !important
+ ::-webkit-scrollbar
+ width : 10px;
+ height: 10px;
+ ::-webkit-scrollbar-thumb
+ border-radius: 10px;
+ background : dark-primary-color-hover;
+ ::-webkit-scrollbar-track
+ background : dark-primary-color
+

body.night
night()

还有一些细节的改动可能会忘记记录于该文档,反正就是跟着自己喜好改就好。

配置完成后,默认并不存在关于(about)的页面,所以执行如下命令添加关于页面,之后你想做任何关于的内容都可以放置到生成的 about.md 文件中了。

1
hexo new page about

部署

站点服务部署

一般可以将 hexo 生成的静态页面部署到像 github 这样的地方,不过我刚好有一台云服务器,所以就直接将整个站点文件夹拷贝到了云服务器中,不想太过麻烦,所以在云服务器中直接建立一个blog 用户来运行博客站点,然后同本地操作一样使用 hexo s -p 8020 来启动站点服务:

1
2
3
4
5
6
useradd blog
su - blog
mkdir site
cd site
npm install -g hexo-cli
// copy blog to here

一般都是将 hexo 服务设为守护进程,每次要重启服务就需要先杀掉原有服务进程,所以这里就简单写个 shell 脚本来处理:

1
2
3
4
5
6
#!/bin/bash
# hexo_restart.sh
arr=(`ps -ef | grep hexo | head -n 1`)
kill -9 ${arr[1]}
rm -f blog.log
nohup hexo s -p 8020 >> blog.log 2>&1 &

协同git自动更新

站点服务能运行起来了,但是如何更新发布文章呢?hexo 服务检测到 source/_post/ 文档有更新的时候,就会自动重新解析文档渲染网页页面,这样的话我便可以在 gitee or github 上建立一个对应 source 目录的仓库,然后在服务器中添加 crontab 定时任务,每隔一段时间 pull 一下远程仓库,这样更新文章的时候就直接提交到远程仓库就可以了。

远程仓库我设计为了 show | write 的分支模型,show 分支上都是可展示到页面的文章,一些还未完成的文章或不想展示的存放在 write 分支,这样 write 分支写好文章后,都是以 fast-forward 的方式合并到 show 分支提交即可。

1
2
crontab -e
# */10 * * * * cd ~/site/source && git pull origin show > /dev/null 2>&1

如果你不想公开你的仓库,那你需要在本地生成相应的公私钥,将公钥内容添加到远程仓库中,然后通过ssh的方式 pull :

1
2
3
4
5
6
ssh-keygen -t rsa -C "ereel@163.com"
eval ssh-agent
ssh-add id_rsa
git pull git@gitee:/ereel/blog.git
crontab -e # add git pull to crontab
# */10 * * * * cd ~/site/source && git pull git@gitee.com/ereel/blog.git > /dev/null 2>&1

Nginx代理与端口映射

现在浏览器要正常访问到博客站点还有一些问题需要解决,一个是我们非 root 用户是不能监听 1000 一下的端口的,但是安全起见,不建议将 hexo 服务直接运行到 root 用户下;还有一个就是现在浏览器访问非 https 站点时都会提示不安全;所以这里需要在root下安装并运行nginx,然后将 blog.ereel.cn 的访问代理到 8020 端口,https 问题通过 Let’s Encrypt 提供证书来解决。具体内容这里不做展开,将 nginx 配置文件贴于下面以供参考:

1
2
# nginx.conf 中注意添加
include conf.d/*.conf;

conf.d/blog.conf:

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
# conf.d/blog.conf
server {
listen 80;
server_name blog.ereel.cn;

return 301 https://$server_name$request_uri;

location / {
proxy_pass http://localhost:8020;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 150;
proxy_send_timeout 100;
proxy_read_timeout 100;
proxy_buffers 4 32k;
client_max_body_size 500m; # Big number is we can post big commits.
client_body_buffer_size 128k;
}
}

server {
listen 443 ssl;
server_name blog.ereel.cn;

# ssl on;
ssl_certificate /etc/letsencrypt/live/ereel.cn/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/ereel.cn/privkey.pem;
ssl_session_timeout 5m;
ssl_protocols SSLv3 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv3:+EXP;
ssl_prefer_server_ciphers on;

location / {
proxy_pass http://localhost:8020;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection upgrade;
proxy_set_header Accept-Encoding gzip;
proxy_connect_timeout 150;
proxy_send_timeout 100;
proxy_read_timeout 100;
proxy_buffers 4 32k;
client_max_body_size 500m; # Big number is we can post big commits.
client_body_buffer_size 128k;
}
}

如果你觉得 nginx 运行于 root 用户也不安全的话,那就做路由端口映射吧,先映射443到普通用户下的 nginx,解密 https 包后代理到 hexo 的 http 服务就可以了。

总结

现在,博客的更新其实就是一次 git commit & git push 的事情了。这样,在任何地方只需要拉取远程仓库,便可以开始写博客,总结自己的所学所思所想啦!

作者

ereel

发布于

2022-02-09

更新于

2022-02-11

许可协议

    


评论