前言:当自己拥有一台电脑时,可以搭建hexo博客,写写自己喜欢的东西,或者用来存档。

Hexo的好处

  • 纯静态博客,部署简单、成本低廉、运行优化非常高效。
  • Hexo 静态博客框架可以在云端,也可以在本地电脑上甚至手机上。
  • Hexo 框架的博客网站没有网站后台,不存在后台安全漏洞的问题。
  • 因为是纯静态的,几乎所有的 CDN 服务都可以完美的加速提升浏览速度。
  • 搜索引擎对纯静态网站有天然的青睐度,收录、权重优先权明显。
  • 纯静态网站会让网络攻击成本大大的增加也就是说纯静态网站被攻击的可能性更低了。

软件安装(Git+Node.Js)

Node.Js下载 官网

Git下载 官网

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1、在D盘创建一个Hexo文件,Hexo文件下再创建一个Git和Nodejs的文件用于软件存储
2、软件安装成功之后,电脑桌面鼠标右键找到Open Git Bash here并打开
3、分别输入
git -v
node -v
npm -v
查看是否会出现版本号。
4、Hexo文件目录里创建一个全局文件,命名随便,我用的是QJ
5、Git Bash:
npm config set prefix "D:\Hexo\QJ"
npm config set cache "D:\Hexo\QJ"
全局变量
6、复制设置全局变量的目录D:\Hexo\QJ
7、打开控制面板-系统安全-系统-高级系统设置-高级-环境变量-用户变量中新建
变量名为Hexo
变量值为D:\Hexo\QJ

安装Hexo框架

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1、Hexo文件目录下创建一个Blog文件夹
2、打开Blog文件,文件中鼠标右键打开Open Git Bash here
3、Git Bash:
npm install -g hexo
安装Hexo框架
4、Git Bash:
hexo -v
查看会不会出现版本号,如果没有报错没有一点问题
5、Git Bash:
hexo init
初始化博客
6、Git Bash:
hexo s
开启本地服务
7、执行成功后会出现一个本地链接,鼠标选中右键Open打开会出现Hexo自带的主题博客

代码部署至托管平台

国外Github

[Github官网](GitHub: Let’s build from here · GitHub)

1
2
3
4
5
6
7
8
9
10
11
12
13
1、Git Bash:ssh-keygen -t rsa -C "3118708520@qq.com"       //生成与gitub连接的密钥
2、打开文件找到后缀为.pub的文件(一般在你C盘的用户文件中「SSH」)打开复制密钥
3、打开Github在个人设置中的SSH把生成下来的密钥和ssh对接
3、修改Hexo根目录下的_config.yml
deploy:
type: git
repo: https://bitbucket.org/JohnSmith/johnsmith.bitbucket.io
branch: main 修改配置文件
4、hexo g 生成静态文件
5、Git Bash: npm install hexo-deployer-git --save 安装插件
6、git config --global user.email "3118708520@qq.com" 配置git信息
git config --global user.name "xiaowentx"
7、hexo d 远程部署博客

重新部署至Github

只要输入以下命令,进行文章全部更新。输完命令后等待几分钟即可。

1、hexo g 
2、hexo clean
3、hexo d

Butterfly主题安装

1
2
3
4
5
6
7
8
9
10
1、首先关闭本地服务Ctrl+C,如果运行两个Open Git Bash here会报错
2、在Blog文件夹中运行Open Git Bash here
3、Git Bash:
git clone -b master https://github.com/jerryc127/hexo-theme-butterfly.git themes/butterfly
进行主题安装(如果安装不了重开Open Git Bash here再试一下,或者试一下npm安装)
npm install hexo-theme-butterfly
4、修改Hexo根目录下的_config.yml把主題改为 butterfly
5.Hexo根目录运行Git并输入
hexo s
查看主题是否已经有了

Butterfly主题配置

1
2
1、主题配置文件在themes下的_config.yml(站点配置文件)
2、Butterfly博客主页 https://butterfly.js.org/(可参考Butterfly博客)

Butterfly主题魔改:友情页面

1
hexo new page link

打开[Blogroot]\source\link\index.md,添加一行type: ‘link’:

1
2
3
4
5
---
title: 友情链接
date: 2025-05-21 17:32:19
type: "link"
---

创建数据文件

新建文件[Blogroot]\source/_data\link.yml,没有_data文件夹的话也请自己新建。以下是默认友链格式示例。打开[Blogroot]\source_data\link.yml,输入:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# flink_style: butterfly / flexcard
- class_name: butterfly排版
class_desc: 这里的每个站点,都耐人寻味……
flink_style: butterfly
link_list:
- name: 标题
link: https://www.test.com/
avatar: https://www.test.com/cs.png
siteshot: https://www.test.com/cs.png
descr: 技术分享,编程学习
type: 技术
- class_name: flexcard排版
class_desc: 这里的每个站点,都耐人寻味……
flink_style: flexcard
link_list:
- name: 码农观测站
link: https://www.test.com/
avatar: https://www.test.com/cs.png
siteshot: https://www.test.com/cs.png
descr: 技术分享,编程学习
type: 技术

注意flink_style为排版参数

1
flink_style: flexcard || butterfly

打开link菜单

取消[Blogroot]_config.butterfly.yml中menu配置项内link页面的注释(这里我已改成中文【友链】)。

1
2
3
4
5
6
7
8
9
10
11
menu:
首页: / || fas fa-home
文章: /archives/ || fas fa-archive
标签: /tags/ || fas fa-tags
分类: /categories/ || fas fa-folder-open
# List||fas fa-list||hide: # 移动端隐藏子菜单
# Music: /music/ || fas fa-music
# Movie: /movies/ || fas fa-video
友链: /link/ || fas fa-link
关于: /about/ || fas fa-heart

替换模板文件

替换[Blogroot]\themes\butterfly\layout\includes\page\flink.pug

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
.container
if top_img === false
h1.page-title= page.title
.flink
if site.data.link
each i in site.data.link
if i.class_name
h2!= i.class_name
if i.class_desc
.flink-desc!=i.class_desc
if i.flink_style === 'flexcard'
.flexcard-flink-list
each item in i.link_list
a.flink-list-card(href=url_for(item.link) target='_blank' data-title=item.descr)
.wrapper.cover
if item.type
.is-type.is-type-0!=item.type
- var siteshot = item.siteshot ? url_for(item.siteshot) : 'https://image.thum.io/get/width/400/crop/800/allowJPG/wait/20/noanimate/' + item.link
if theme.lazyload.enable
img.cover.fadeIn(data-lazy-src=siteshot onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.post_page) + `'` alt='' )
else
img.cover.fadeIn(src=siteshot onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.post_page) + `'` alt='' )
.info
if theme.lazyload.enable
img.flink-avatar(data-lazy-src=url_for(item.avatar) onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.flink) + `'` alt='' )
else
img(src=url_for(item.avatar) onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.flink) + `'` alt='' )
span.flink-sitename= item.name
span.flink-sitedesc(title=item.descr)= item.descr
else if i.flink_style === 'butterfly'
.butterfly-flink-list
each item in i.link_list
.flink-list-item
a(href=url_for(item.link) title=item.name target="_blank")
.flink-item-icon
if theme.lazyload.enable
img(data-lazy-src=url_for(item.avatar) onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.flink) + `'` alt=item.name )
else
img(src=url_for(item.avatar) onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.flink) + `'` alt=item.name )
.flink-item-info
.flink-item-name= item.name
.flink-item-desc(title=item.descr)= item.descr
!= page.content

替换样式文件

替换[Blogroot]\themes\butterfly\source\css_page\flink.styl

注意代码中#article-container,检查一下你的Butterfly主题link页面div是不是用的这个id,如果不是的部署将没有样式

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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
#article-container
.flink
margin-bottom: 20px
.flink-desc
margin: 0 0 .6rem !important
.butterfly-flink-list
overflow: auto
text-align: center

& > .flink-list-item
position: relative
float: left
overflow: hidden
margin: 15px 7px
width: calc(100% / 3 - 15px)
height: 90px
line-height: 17px
-webkit-transform: translateZ(0)
addBorderRadius(8)
background: #49b1f514

+maxWidth1024()
width: calc(50% - 15px) !important

+maxWidth600()
width: calc(100% - 15px) !important

&:hover
.flink-item-icon
margin-left: -10px
width: 0

&:before
position: absolute
top: 0
right: 0
bottom: 0
left: 0
z-index: -1
background: var(--text-bg-hover)
content: ''
transition: transform .3s ease-out
transform: scale(0)

&:hover:before,
&:focus:before,
&:active:before
transform: scale(1)

a
color: var(--font-color)
text-decoration: none

.flink-item-icon
float: left
overflow: hidden
margin: 15px 10px
width: 60px
height: 60px
border-radius: 30%
transition: width .3s ease-out

img
width: 100%
height: 100%
transition: filter 375ms ease-in .2s, transform .3s
object-fit: cover

.img-alt
display: none

:hover
color: #fff

.flexcard-flink-list
display: flex
flex-wrap: wrap
justify-content: flex-start
margin: -8px
align-items: stretch
> .flink-list-card
margin: 8px
width: calc(100% / 4 - 16px)
display: block
line-height: 1.4
height: 100%
text-decoration:none
.cover
width: 100%
height: 120px
overflow: hidden
border-radius: 6px
box-shadow: 0 1px 2px 0px rgba(0, 0, 0, 0.2)
background: #f6f6f6
position: relative
.is-type
position: absolute
top: 0
left: 0
color: #fff
z-index: 10
border-radius: 6px 0 6px 0
padding: 4px 8px
font-size: .6rem
background-color: var(--btn-bg)
img
width: 100%
height: 100%
pointer-events: none
transition: transform 2s ease
object-fit: cover

.info
margin-top: 8px
img
width: 32px
height: 32px
pointer-events: none
border-radius: 16px
float: left
margin: 0 auto .1rem !important
margin-right: 8px !important
.flink-sitename
font-weight: 600
font-size: var(--global-font-size)
color: var(--font-color)
display: -webkit-box
-webkit-box-orient: vertical
overflow: hidden
-webkit-line-clamp: 1
transition: all 0.28s ease
-moz-transition: all 0.28s ease
-webkit-transition: all 0.28s ease
-o-transition: all 0.28s ease
.flink-sitedesc
margin-top: 4px !important
font-size: var(--global-font-size);
word-wrap: break-word
line-height: 1.2
color: #888
display: -webkit-box
-webkit-box-orient: vertical
overflow: hidden
-webkit-line-clamp: 2
:hover
.cover
box-shadow: 0 4px 8px 0px rgba(0, 0, 0, 0.1), 0 2px 4px 0px rgba(0, 0, 0, 0.1), 0 4px 8px 0px rgba(0, 0, 0, 0.1), 0 8px 16px 0px rgba(0, 0, 0, 0.1)
.flink-sitename
color: var(--tzy-theme) !important


.flink-item-name
@extend .limit-one-line
padding: 16px 10px 0 0
height: 40px
font-weight: bold
font-size: 1.43em

.flink-item-desc
@extend .limit-one-line
padding: 16px 10px 16px 0
height: 50px
font-size: .93em

.flink-name
margin-bottom: 5px
font-weight: bold
font-size: 1.5em

全部保存好之后,一键三连部署本地预览

1
hexo clean; hexo g;hexo s 

效果图

友情链接预览图

Butterfly主题魔改:分类页面

安装插件

1
npm install hexo-butterfly-categories-card --save

新建样式文件

在博客根目录themes\butterfly\source\css\下新建categorybar.css文件,添加 https://npm.elemecdn.com/hexo-butterfly-categories-card@1.0.0/lib/categorybar.css 的代码。

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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#categoryBar {
width: 100% !important;
}
ul.categoryBar-list {
margin: 5px 5px 0 5px !important;
padding: 0 !important;
}
li.categoryBar-list-item {
font-weight: bold;
display: inline-block;
height: 180px !important;
margin: 5px 0.5% 0 0.5% !important;
background-image: linear-gradient(rgba(0,0,0,0.4) 25%, rgba(16,16,16,0) 100%);
border-radius: 10px;
padding: 25px 0 25px 25px !important;
box-shadow: rgba(50,50,50,0.3) 50px 50px 50px 50px inset;
overflow: hidden;
background-size: 100% !important;
background-position: center !important;
}
li.categoryBar-list-item:hover {
background-size: 110% !important;
box-shadow: inset 500px 50px 50px 50px rgba(50,50,50,0.6);
}
li.categoryBar-list-item:hover span.categoryBar-list-descr {
transition: all 0.5s;
transform: translate(-100%, 0);
}
a.categoryBar-list-link {
color: #fff !important;
font-size: 20px !important;
}
a.categoryBar-list-link::before {
content: '|' !important;
color: #fff !important;
font-size: 20px !important;
}
a.categoryBar-list-link:after {
content: '';
position: relative;
width: 0;
bottom: 0;
display: block;
height: 3px;
border-radius: 3px;
background-color: #fff;
}
a.categoryBar-list-link:hover:after {
width: 90%;
left: 1%;
transition: all 0.5s;
}
span.categoryBar-list-count {
display: block !important;
color: #fff !important;
font-size: 20px !important;
}
span.categoryBar-list-count::before {
content: '\f02d' !important;
padding-right: 15px !important;
display: inline-block;
font-weight: 600;
font-style: normal;
font-variant: normal;
font-family: 'Font Awesome 6 Free';
text-rendering: auto;
-webkit-font-smoothing: antialiased;
}
span.categoryBar-list-descr {
padding: 5px;
display: block !important;
color: #fff !important;
font-size: 20px !important;
position: relative;
right: -100%;
}
@media screen and (max-width: 650px) {
li.categoryBar-list-item {
width: 48% !important;
height: 150px !important;
margin: 5px 1% 0 1% !important;
}
}

修改插件js样式文件

打开博客根目录下node_modules\hexo-butterfly-categories-card\index.js文件,全部替换成以下代码:

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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
'use strict'
// 全局声明插件代号
const pluginname = 'butterfly_categories_card'
// 全局声明依赖
const pug = require('pug')
const path = require('path')
const urlFor = require('hexo-util').url_for.bind(hexo)
const util = require('hexo-util')

hexo.extend.filter.register('after_generate', function () {

// =====================================================================
// 首先获取整体的配置项名称
const config = hexo.config.categoryBar || hexo.theme.config.categoryBar
// 如果配置开启
if (!(config && config.enable)) return
// 获取所有分类
var categories_list= hexo.locals.get('categories').data;
var categories_message= config.message;
//声明一个空数组用来存放合并后的对象
var new_categories_list = [];
// 合并分类属性和新添加的封面描述属性
// 合并分类属性和新添加的封面描述属性
for (var i = 0; i < categories_list.length; i++) {
var a = categories_list[i];
var b = categories_message[i];
// 确保不覆盖原分类路径
new_categories_list[i] = Object.assign({}, a, { path: a.path }, b);
}
// console.log(new_categories_list)
// 集体声明配置项
const data = {
pjaxenable: hexo.theme.config.pjax.enable,
enable_page: config.enable_page ? config.enable_page : "/",
layout_type: config.layout.type,
layout_name: config.layout.name,
layout_index: config.layout.index ? config.layout.index : 0,
categories_list: new_categories_list,
column: config.column ? config.column : odd, // odd:3列 | even:4列
row: config.row ? config.row : 2, //显示行数,默认两行,超过行数切换为滚动显示
custom_css: config.custom_css ? urlFor(config.custom_css) : "https://cdn.jsdelivr.net/npm/hexo-butterfly-categories-card/lib/categorybar.css"
}
// 渲染页面
const temple_html_text = config.temple_html ? config.temple_html : pug.renderFile(path.join(__dirname, './lib/html.pug'),data);

//cdn资源声明
//样式资源
const css_text = `<link rel="stylesheet" href="${data.custom_css}">`
//注入容器声明
var get_layout
//若指定为class类型的容器
if (data.layout_type === 'class') {
//则根据class类名及序列获取容器
get_layout = `document.getElementsByClassName('${data.layout_name}')[${data.layout_index}]`
}
// 若指定为id类型的容器
else if (data.layout_type === 'id') {
// 直接根据id获取容器
get_layout = `document.getElementById('${data.layout_name}')`
}
// 若未指定容器类型,默认使用id查询
else {
get_layout = `document.getElementById('${data.layout_name}')`
}

//挂载容器脚本
//挂载容器脚本(动态创建容器)
var user_info_js = `<script data-pjax>
function ${pluginname}_injector_config(){
// 检查容器是否存在
var parent_div_git = ${get_layout};
// 如果容器不存在,则动态创建
if (!parent_div_git) {
console.warn('${pluginname}: 挂载容器不存在,正在动态创建...');
// 创建新容器(默认插入到页面主体顶部)
parent_div_git = document.createElement('div');
parent_div_git.id = '${data.layout_name}'; // 赋予配置的ID
document.querySelector('#page').prepend(parent_div_git); // 插入到 #content-inner 内
}
var item_html = '${temple_html_text}';
console.log('已挂载 ${pluginname}');
parent_div_git.insertAdjacentHTML("afterbegin",item_html)
}
// 路径匹配逻辑(使用 startsWith)
if (location.pathname.startsWith('${data.enable_page}') || '${data.enable_page}' === 'all') {
${pluginname}_injector_config();
}
</script>`
// 注入用户脚本
// 此处利用挂载容器实现了二级注入
hexo.extend.injector.register('body_end', user_info_js, "default");
// 注入样式资源
hexo.extend.injector.register('head_end', css_text, "default");
},
hexo.extend.helper.register('priority', function(){
// 过滤器优先级,priority 值越低,过滤器会越早执行,默认priority是10
const pre_priority = hexo.config.categoryBar.priority || hexo.theme.config.categoryBar.priority
const priority = pre_priority ? pre_priority : 10
return priority
})
)

修改插件html.pug文件

打开博客根目录下node_modules\hexo-butterfly-categories-card\lib\html.pug文件,全部替换成以下代码:

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
- var prow = 190 * row + 'px'
- var mrow = 160 * row + 'px'

if (column === 'odd')
style.
li.categoryBar-list-item{width:32.3%;}.categoryBar-list{max-height: #{prow};overflow:auto;}.categoryBar-list::-webkit-scrollbar{width:0!important}@media screen and (max-width: 650px){.categoryBar-list{max-height: #{mrow};}}
else if (column === 'even')
style.
li.categoryBar-list-item{width:24%;}.categoryBar-list{max-height: #{prow};overflow:auto;}.categoryBar-list::-webkit-scrollbar{width:0!important}@media screen and (max-width: 650px){.categoryBar-list{max-height: #{mrow};}}
.recent-post-item(style='height:auto;width:100%;padding:0px;')
#categoryBar
ul.categoryBar-list
if pjaxenable
each cl in categories_list
li.categoryBar-list-item(style=`background:url(` + cl.cover + `);`)
//- 强制修正路径:移除重复的 categories 前缀
- var cleanPath = cl.path.replace(/^\/?categories\//, '')
a.categoryBar-list-link(
onclick=`pjax.loadUrl("/categories/${cleanPath}");`
href='javascript:void(0);'
)= cl.name
span.categoryBar-list-count= cl.length
span.categoryBar-list-descr= cl.descr
else
each cl in categories_list
li.categoryBar-list-item(style=`background:url(` + cl.cover + `);`)
//- 直接输出修正后的路径
- var cleanPath = cl.path.replace(/^\/?categories\//, '')
a.categoryBar-list-link(href=`/categories/${cleanPath}`)= cl.name
span.categoryBar-list-count= cl.length
span.categoryBar-list-descr= cl.descr

修改配置文件

在博客根目录下_config.butterfly.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
# hexo-butterfly-categories-card
# see https://akilar.top/posts/a9131002/
categoryBar:
enable: true # 开关
priority: 5 #过滤器优先权
enable_page: /categories/ # 应用页面
layout: # 挂载容器类型
type: id
name: recent-posts
index: 0
column: odd # odd:3列 | even:4列
row: 5 #显示行数,默认两行,超过行数切换为滚动显示
message:
- descr: 1
cover: /img/11.png
- descr: 2
cover: /img/12.png
- descr: 3
cover: /img/13.png
- descr: 4
cover: /img/14.png
- descr: 5
cover: /img/15.png
- descr: 6
cover: /img/16.png
- descr: 7
cover: /img/17.png
- descr: 8
cover: /img/18.png
custom_css: /css/categorybar.css

效果图

更换自己的域名

1、在博客的blog下的.deploy_git目录下创建名为CNAME的文本文档

2、去自己购买域名的地方把域名解析

3、添加两个记录第一个主机名为@类型选择CNAME对应值的话就是github的地址比如xxxxx.github.io,第二个主机名为www类型为A记录对应值则是你ping到github上创建博客的ip地址

4、进入github的Your repositories->你所建立的储存库->Settings->Pages->在Custom domain中填写你购买的域名就OK了。

Hexo的基本命令

hexo博客文章采用Markdown语法

1
2
3
4
hexo init  初始化博客
hexo n title 创建一篇新的文章,文章标题是title
hexo new page tags 新建标签页
hexo new "hexo" 新建标题名为hexo的文章

Hexo搬移

1.拷贝相关文件

建立hexo博客都会有一个独立的文件夹。电脑转移时安全的做法是将整个文件夹拷贝,这其中包括三个必备的文件:config.yml(站点配置_)、theme(主题文件夹)、source(博客内容文件)、_config.butterfly.yml(主题配置文件)。

次要文件:scaffolds(文章的模板)、package.json(使用包的说明文件)和.gitignore(限定在提交的时候哪些文件可以忽略)三个次要文件为自动生成的,因此丢失也不影响博客内容,后续在hexo init时会生成这三个文件。

需要删除的文件:.git文件、node_modules(进行npm install会重新生成)、public(执行hexo g时会重新生成)、.deploy_git文件夹(执行hexo d时会重新生成)、db.json文件。其实上面这些可删除的文件即为.gitignore文件里面记载的可以忽略的内容。

2.在新电脑上重新安装git

3.替换掉git之前的SSH