安装Hexo

1
2
3
4
npm install hexo-cli -g
hexo init
npm install hexo-renderer-pug hexo-renderer-stylus --save
npm install hexo-deployer-git --save

安装Solitude

1
git clone -b main https://github.com/everfu/hexo-theme-solitude.git themes/solitude

在博客根目录运行bash命令,将主题的配置文件复制到根目录,以便方便配置主题。

1
cp -rf ./themes/solitude/_config.yml ./_config.solitude.yml
1
copy .\themes\solitude\_config.yml .\_config.solitude.yml

配套插件

Solitude外挂标签

1
npm install hexo-solitude-tag

文章生成短链接

1
npm install hexo-abbrlink --save

_config.yml找到#url修改以下:

1
2
3
4
5
6
7
8
9
10
11
12
13
# URL
## Set your site url here. For example, if you use GitHub Page, set url as 'https://username.github.io/project'
url: https://www.jinjun.top
#permalink: :year/:month/:day/:title/
#permalink_defaults:
permalink: posts/:abbrlink.html
# 文章链接转:https://github.com/rozbo/hexo-abbrlink
abbrlink:
alg: crc16 #support crc16(default) and crc32
rep: hex #support dec(default) and hex
pretty_urls:
trailing_index: true # Set to false to remove trailing 'index.html' from permalinks
trailing_html: true # Set to false to remove trailing '.html' from permalinks

本地搜索

1
npm install hexo-generator-search --save

algolia搜索

1
npm install hexo-algoliasearch --save

申请Id/API地址:https://www.algolia.com/

_congif.yml添加配置内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# algolia搜索: https://github.com/LouisBarranqueiro/hexo-algoliasearch
algolia:
appId: "Z7A3XW4R2I"
apiKey: "12db1ad54372045549ef465881c17e743"
adminApiKey: "40321c7c207e7f73b63a19aa24c4761b"
chunkSize: 5000
indexName: "my-hexo-blog"
fields:
- content:strip:truncate,0,500
- excerpt:strip
- gallery
- permalink
- photos
- slug
- tags
- title

Rss

1
npm install hexo-generator-feed --save

Sitemap

1
npm install hexo-generator-sitemap --save

_congig.yml添加配置内容:

1
2
3
4
5
# https://github.com/hexojs/hexo-generator-sitemap
sitemap:
path: sitemap.xml
tags: true
categories: true

BaiduSitemap

1
npm install hexo-generator-baidu-sitemap --save

_congig.yml 添加配置内容

1
2
baidusitemap: 
path: baidusitemap.xml

hexo-indexnow

Bing搜索引擎,IndexNow插件

1
npm install hexo-indexnow --save

_config.yml 添加配置内容

1
2
3
4
5
6
7
8
hexo_indexnow:
count: latest # 数字或者 "latest"(=1)
txt_name: indexnow.txt # 链接文件名
apikey: xxxxxx # 你的 apikey
server: bing # indexnow 服务器,可选值有:bing、yandex、indexnow

deploy:
- type: indexnow_url_submitter

字数统计

1
npm install hexo-wordcount --save

安全转跳插件

1
npm install hexo-safego --save

_config.yml 添加配置内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# hexo-safego安全跳转插件
# see https://blog.liushen.fun/posts/1dfd1f41/
hexo_safego:
enable: true # 是否启用 hexo-safego 插件
enable_base64_encode: true # 是否启用 Base64 编码链接
enable_target_blank: true # 是否在跳转链接中添加 target="_blank"
url_param_name: 'u' # URL 参数名,用于生成跳转链接
html_file_name: 'go.html' # 跳转页面文件名
ignore_attrs: # 需要忽略的链接属性列表
- 'data-fancybox'
apply_containers: # 容器 ID 列表,如果为空则匹配整个 body
- '#article-container'
domain_whitelist: # 域名白名单列表,包含白名单中的域名的链接将被忽略
- 'jinjun.top'
apply_pages: # 生效页面路径列表,只有在这些页面上才会对链接进行处理
- '/posts/'
avatar: /img/siteicon/manifest-icon-192.maskable.png # 头像图片链接
title: "钧言极客" # 标题
subtitle: "安全中心" # 副标题
darkmode: true # 是否启用夜间模式
debug: false # 是否启用调试模式,开启后会输出详细的调试信息

Gulp

1
npm install gulp compress gulp-clean-css gulp-html-minifier-terser gulp-htmlclean gulp-terser --save-dev

在博客根目录新建 gulpfile.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
var gulp = require('gulp');
var cleanCSS = require('gulp-clean-css');
var htmlmin = require('gulp-html-minifier-terser');
var htmlclean = require('gulp-htmlclean');
var terser = require('gulp-terser');
// 压缩js
gulp.task('compress', () =>
gulp.src(['./public/**/*.js', '!./public/**/*.min.js'])
.pipe(terser())
.pipe(gulp.dest('./public'))
)
//压缩css
gulp.task('minify-css', () => {
return gulp.src(['./public/**/*.css'])
.pipe(cleanCSS({
compatibility: 'ie11'
}))
.pipe(gulp.dest('./public'));
});
//压缩html
gulp.task('minify-html', () => {
return gulp.src('./public/**/*.html')
.pipe(htmlclean())
.pipe(htmlmin({
removeComments: true, //清除html注释
collapseWhitespace: true, //压缩html
collapseBooleanAttributes: true,
//省略布尔属性的值,例如:<input checked="true"/> ==> <input />
removeEmptyAttributes: true,
//删除所有空格作属性值,例如:<input id="" /> ==> <input />
removeScriptTypeAttributes: true,
//删除<script>的type="text/javascript"
removeStyleLinkTypeAttributes: true,
//删除<style>和<link>的 type="text/css"
minifyJS: true, //压缩页面 JS
minifyCSS: true, //压缩页面 CSS
minifyURLs: true //压缩页面URL
}))
.pipe(gulp.dest('./public'))
});

// 运行gulp命令时依次执行以下任务
gulp.task('default', gulp.parallel(
'compress', 'minify-css', 'minify-html'
))

Swpp

1
npm install hexo-swpp swpp-backends --save

在博客根目录新建 sw-rules.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
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
module.exports.config = {
/** @type {?ServiceWorkerConfig|boolean} */
serviceWorker: {
escape: 0,
cacheName: 'SolitudeCache',
debug: false,
},
register: {
onsuccess: undefined,
onerror: () =>
console.error(
'Service Worker 注册失败!可能是由于您的浏览器不支持该功能!'
),
builder: (root, framework, pluginConfig) => {
const { onerror, onsuccess } = pluginConfig.register;
return `
<script>
(() => {
const sw = navigator.serviceWorker;
const error = ${onerror && onerror.toString()};
if (!sw?.register('${new URL(root).pathname}sw.js')
${onsuccess ? `?.then(${onsuccess.toString()})` : ""}
?.catch(error)
) error()
})()
</script>`;
},
},
/** @type {?DomConfig|boolean} */
dom: {
/** @type {?VoidFunction} */
onsuccess: () => {
caches
.match(location.href)
.then((res) => {
if (res)
res.json().then((json) => {
utils &&
utils.snackbarShow(
`已刷新缓存,更新为${json.global + '.' + json.local
}版本最新内容`,
false,
2000
);
});
else console.info('未找到缓存');
})
.catch((error) => console.error('缓存匹配出错', error));
},
},
/** @type {?VersionJsonConfig|boolean} */
json: {
/** @type {number} */
maxHtml: 15,
/** @type {number} */
charLimit: 1024,
/** @type {string[]} */
merge: [],
exclude: {
/** @type {RegExp[]} */
localhost: [],
/** @type {RegExp[]} */
other: [],
},
},
/** @type {?ExternalMonitorConfig|boolean} */
external: {
/** @type {number} */
timeout: 5000,
/** 拉取文件时地并发限制 */
concurrencyLimit: 100,
/** @type {({head: string, tail: string}|function(string):string[])[]} */
js: [],
/** @type {RegExp[]} */
stable: [
/^https:\/\/npm\.elemecdn\.com\/[^/@]+\@[^/@]+\/[^/]+\/[^/]+$/,
/^https:\/\/cdn\.cbd\.int\/[^/@]+\@[^/@]+\/[^/]+\/[^/]+$/,
/^https:\/\/cdn\.jsdelivr\.net\/npm\/[^/@]+\@[^/@]+\/[^/]+\/[^/]+$/,
],
replacer: (srcUrl) => {
if (srcUrl.startsWith('https://cdn.jsdelivr.net/npm/')) {
const pathname = new URL(srcUrl).pathname;
return [
srcUrl,
`https://cdn.cbd.int/${pathname}`,
`https://npm.elemecdn.com/${pathname}`,
`https://fastly.jsdelivr.net/npm/${pathname}`,
];
} else {
return srcUrl;
}
},
},
};

module.exports.cacheRules = {
simple: {
clean: true,
search: false,
match: (url, $eject) =>
url.host === $eject.domain && ['/404.html'].includes(url.pathname),
},
cdn: {
clean: true,
match: (url) =>
[
'cdn.cbd.int',
'lf26-cdn-tos.bytecdntp.com',
'lf6-cdn-tos.bytecdntp.com',
'lf3-cdn-tos.bytecdntp.com',
'lf9-cdn-tos.bytecdntp.com',
'cdn.staticfile.org',
'npm.elemecdn.com',
].includes(url.host) &&
url.pathname.match(/\.(js|css|woff2|woff|ttf|cur)$/),
},
};

module.exports.getSpareUrls = (srcUrl) => {
if (srcUrl.startsWith('https://npm.elemecdn.com')) {
return {
timeout: 3000,
list: [
srcUrl,
`https://fastly.jsdelivr.net/${new URL(srcUrl).pathname}`,
],
};
}
};

module.exports.ejectValues = (hexo, rules) => {
return {
domain: {
prefix: 'const',
value: new URL(hexo.config.url).host,
},
};
};

module.exports.skipRequest = (request) => request.url.startsWith("https://i0.hdslb.com") ||
request.url.startsWith('https://meting.qjqq.cn') ||
request.url.startsWith('https://api.i-meto.com');