Next升级+Mac迁移

写博客到现在已经快一年了,Next主题也更新了好多版本,新增的pjax真的是太香了,果断更新。顺便把Hexo迁移到mac上面来

更新说明

Next主题从7.1到7.7.2的变动较大,直接升级的话小问题比较多,所以这次升级采用了重新安装的方式

版本对比

升级前Hexo版本

1
2
3
4
5
hexo: 3.8.0
hexo-cli: 3.1.0
os: Windows_NT 10.0.17763 win32 x64
node: 12.14.1
next: 7.1

升级后Hexo版本

1
2
3
4
5
hexo: 4.2.0
hexo-cli: 3.1.0
os: Darwin 18.7.0 darwin x64
node: 13.10.1
next: 7.7.2

新增功能

  • pjax(局部刷新加载页面)
  • DarkMode夜间模式(支持Mac等的夜间模式)
  • Gitalk评论(Gitment凉了之后一直没设置评论系统,这次顺路加上)
  • Mediumzoom(图片插件)
  • 中英切换(新)
  • CDN
  • Echarts

移除功能

  • 动态背景(占用资源较大,在手机平板等设备上造成卡顿、发热、耗电快等问题)
  • i18n-generator(一年也没写过英语的博客,而且这个方案缺陷太大)
  • 网易云音乐挂件(使用频率极低,拖慢加载速度)

保留功能

  • 站内搜索
  • 字数与阅读时长统计
  • 网站运行时间
  • 加载进度条
  • 崩溃欺骗
  • 背景图片
  • 鼠标点击特效
  • 不蒜子
  • Live2D看板娘

Mac安装过程

安装软件依赖

首先下载安装gitnode.js,官网如下

安装完成后在终端分别输入

1
2
git --version
node -v

检测是否安装成功,成功的话会返回软件版本号

配置本地目录

  • 新建一个用于存放博客文件的文件夹
  • 新建位于文件夹位置的终端窗口
  • 输入npm install hexo -g安装hexo
    • 这一步可能会报错,报错的话使用命令sudo npm install --unsafe-perm --verbose -g hexo来安装hexo
  • 输入npm install安装其他依赖
  • 输入npm install hexo-deployer-git --save安装部署插件
  • 输入hexo v查看是否安装成功,成功会返回版本号

配置ssh

  • 打开终端
  • 输入ls -al ~/.ssh检查是否有以前生成的 SSH Key,没有的话继续
  • 输入ssh-keygen -t rsa -C "Guthub邮箱地址" 然后回车三连
  • 此时终端会显示文件的生成路径,根据路径找到并打开id_rsa.pub
  • 复制里面的所有内容
  • 打开Github,在右上角个人头像下拉菜单中找到Settings
  • 打开SSH and GPG keys,点击右上角New SSH key
  • Title随便填,然后在Key中粘贴
  • 点击Add SSH key
  • 回到Git bash,输入ssh -T git@github.com回车
  • 首次输入可能会有提醒,输入yes回车即可
  • 成功返回Hi 用户名! You've successfully authenticated, but GitHub does not provide shell access.就代表成功了
  • 输入git config --global user.name "用户名"
  • 输入git config --global user.email "邮箱地址"

安装Next主题

在终端输入下面的命令安装最新的Next主题

1
git clone https://github.com/theme-next/hexo-theme-next themes/next

Next主题自定义

Hexo的配置过程我就不说了,根据原来的_config.yml配置就行,下面要说的是Next主题的配置

配置文件分离

Next主题在7.3之后分离了配置文件与主题,详情请见小丁的个人博客

  • 新建文件夹hexo/source/_data
  • ./themes/next/_config.yml复制到hexo/source/_data路径下并重命名为next.yml
  • next.yml中的override设置为true即可作为主题的配置文件使用
  • hexo/source/_data中新建body-end.swigstyles.styl文件
  • 然后在next.ymlcustom_file_path中删除前面的#来启用bodyEndstyle
  • custom_file_path中的其他选项根据需要创建相关文件并启用

Pjax

Pjax是基于Ajax的插件,能实现网页局部无刷新载入,听起来很香,然而存在一些小问题:

  • 使用Mediumzoom时,从归档进入博文不会加载图片,需要刷新网页才能加载
  • Echarts图表全部需要刷新才能显示,否则只有一片空白

安装Pjax

1
git clone https://github.com/theme-next/theme-next-pjax source/lib/pjax

next.yml中搜索pjax并设置为

1
pjax: true

Darkmode

Next主题新增了暗色模式,能够配合系统的暗色主题使用
next.yml中搜索darkmode并设置为auto即可根据系统主题切换亮色/暗色模式

Gitalk评论

评论系统,一开始想用Valine来着,结果要实名制,果断弃了

  • 在Github新建一个仓库gitalk-comment,用来存放评论产生的issues
  • 点击右上角头像 - Setting - Developer settings - OAuth Apps - New OAuth Apps
  • Application name 随便填
  • Homepage URLAuthorization callback URL都填自己的博客地址
  • 点击 Register application
  • next.yml中搜索gitalk
  • 复制得到的Cilent IDCilent secret到相应位置粘贴
  • 设置enabletrue
  • github_idadmin_user为你的用户名
  • repo为刚才创建的仓库名gitalk-comment
  • distraction_free_mode是类似facobook的评论遮罩功能

next.yml中的具体配置如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Gitalk
# For more information: https://gitalk.github.io, https://github.com/gitalk/gitalk
gitalk:
enable: true
github_id: Siriusq # GitHub repo owner
repo: gitalk-commnet # Repository name to store issues
client_id: xxxxxxxx # GitHub Application Client ID
client_secret: xxxxxxxx # GitHub Application Client Secret
admin_user: Siriusq # GitHub repo owner and collaborators, only these guys can initialize gitHub issues
distraction_free_mode: false # Facebook-like distraction free mode
# Gitalk's display language depends on user's browser or system environment
# If you want everyone visiting your site to see a uniform language, you can set a force language value
# Available values: en | es-ES | fr | ru | zh-CN | zh-TW
language:

Mediumzoom

模仿Medium图片查看方式的插件
安装

1
npm install medium-zoom

next.yml中搜索mediumzoom并设置为

1
mediumzoom: true

中英切换

请移步另一篇博客Hexo Next 7.7 双语切换

站内搜索

查找博客内的内容
安装

1
npm install hexo-generator-searchdb

next.yml中搜索local_search并设置为

1
enable: true

字数与阅读时长统计

安装

1
npm install hexo-symbols-count-time

在根目录的_config.yml中添加

1
2
3
4
5
6
7
8
9
symbols_count_time:
symbols: true
time: true
total_symbols: true
total_time: true
exclude_codeblock: false
awl: 4
wpm: 275
suffix: "mins."

然后在next.yml中搜索symbols_count_time并设置为

1
2
3
4
symbols_count_time:
separated_meta: true
item_text_post: true
item_text_total: true

添加jquery

  • 新版的Next主题移除了jquery,导致一些老得自定义设置会失效,我直接从老版本的Next主题复制过来了,路径是./hexo/themes/next/source/libs/jquery/jquert-2.2.0.min.js,也可以到官网下载
  • 将jquery放置在./hexo/source/js路径下
  • ./hexo/source/_data/body-end.swig添加,版本不同的话记得改下面的版本
    1
    2
    <!--jquery-->
    <script type="text/javascript" src="/js/jquery-2.2.0.min.js"></script>

网站运行时间

打开./hexo/themes/next/layout/_partials/footer.swig并添加下列代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<div>
<span id="timeDate">载入天数...</span><span id="times">载入时分秒...</span>
<script>
var now = new Date();
function createtime() {
var grt= new Date("03/31/2019 00:00:00");
now.setTime(now.getTime()+250);
days = (now - grt ) / 1000 / 60 / 60 / 24; dnum = Math.floor(days);
hours = (now - grt ) / 1000 / 60 / 60 - (24 * dnum); hnum = Math.floor(hours);
if(String(hnum).length ==1 ){hnum = "0" + hnum;} minutes = (now - grt ) / 1000 /60 - (24 * 60 * dnum) - (60 * hnum);
mnum = Math.floor(minutes); if(String(mnum).length ==1 ){mnum = "0" + mnum;}
seconds = (now - grt ) / 1000 - (24 * 60 * 60 * dnum) - (60 * 60 * hnum) - (60 * mnum);
snum = Math.round(seconds); if(String(snum).length ==1 ){snum = "0" + snum;}
document.getElementById("timeDate").innerHTML = "本站已安全运行 "+dnum+"";
document.getElementById("times").innerHTML = hnum + " 小时 " + mnum + "" + snum + "";
}
setInterval("createtime()",250);
</script>
</div>

加载进度条

显示当前网页的加载进度
安装

1
git clone https://github.com/theme-next/theme-next-pace source/lib/pace

next.yml中搜索Progress bar in the top during page loading并设置为

1
2
pace:
enable: true

崩溃欺骗

在网页标题中添加崩溃欺骗效果,离开页面后标题会更改,切换回来后会恢复正常,需要配合jquery使用

./hexo/source/js中新建crash_cheat文件,复制下列代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!--崩溃欺骗-->
var OriginTitle = document.title;
var titleTime;
document.addEventListener('visibilitychange', function () {
if (document.hidden) {
$('[rel="icon"]').attr('href', "/img/TEP.ico");
document.title = '╭(°A°`)╮ 页面崩溃啦 ~';
clearTimeout(titleTime);
}
else {
$('[rel="icon"]').attr('href', "/favicon.ico");
document.title = '(ฅ>ω<*ฅ) 噫又好了~' + OriginTitle;
titleTime = setTimeout(function () {
document.title = OriginTitle;
}, 2000);
}
});

然后在./hexo/source/_data/body-end.swig中添加

1
2
<!--崩溃欺骗-->
<script type="text/javascript" src="/js/crash_cheat.js"></script>

背景图片

将背景图片放置在./hexo/themes/next/source/images中并命名为background.jpg
然后在./hexo/source/_data/styles.styl中添加

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
body {
background:url(/images/background.jpg);//图片路径
background-repeat: no-repeat;//是否重复平铺
background-attachment: fixed;//是否随着网页上下滚动而滚动,fixed为固定
background-position: 50% 50%;//图片位置
background-size: cover;//图片展示大小
-webkit-background-size: cover;
-o-background-size: cover;
-moz-background-size: cover;
-ms-background-size: cover;
opacity: 0.9;
footer > div > div {
color:#000000;//底部文字颜色
}
}

鼠标点击特效

根据小丁的个人博客更换了鼠标点击的特效,原来的特效对低性能设备不友好
./hexo/themes/next/source/js/cursor中新建fireworks.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
143
144
145
146
147
148
149
150
151
152
153
154
class Circle {
constructor({ origin, speed, color, angle, context }) {
this.origin = origin
this.position = { ...this.origin }
this.color = color
this.speed = speed
this.angle = angle
this.context = context
this.renderCount = 0
}

draw() {
this.context.fillStyle = this.color
this.context.beginPath()
this.context.arc(this.position.x, this.position.y, 2, 0, Math.PI * 2)
this.context.fill()
}

move() {
this.position.x = (Math.sin(this.angle) * this.speed) + this.position.x
this.position.y = (Math.cos(this.angle) * this.speed) + this.position.y + (this.renderCount * 0.3)
this.renderCount++
}
}

class Boom {
constructor ({ origin, context, circleCount = 16, area }) {
this.origin = origin
this.context = context
this.circleCount = circleCount
this.area = area
this.stop = false
this.circles = []
}

randomArray(range) {
const length = range.length
const randomIndex = Math.floor(length * Math.random())
return range[randomIndex]
}

randomColor() {
const range = ['8', '9', 'A', 'B', 'C', 'D', 'E', 'F']
return '#' + this.randomArray(range) + this.randomArray(range) + this.randomArray(range) + this.randomArray(range) + this.randomArray(range) + this.randomArray(range)
}

randomRange(start, end) {
return (end - start) * Math.random() + start
}

init() {
for(let i = 0; i < this.circleCount; i++) {
const circle = new Circle({
context: this.context,
origin: this.origin,
color: this.randomColor(),
angle: this.randomRange(Math.PI - 1, Math.PI + 1),
speed: this.randomRange(1, 6)
})
this.circles.push(circle)
}
}

move() {
this.circles.forEach((circle, index) => {
if (circle.position.x > this.area.width || circle.position.y > this.area.height) {
return this.circles.splice(index, 1)
}
circle.move()
})
if (this.circles.length == 0) {
this.stop = true
}
}

draw() {
this.circles.forEach(circle => circle.draw())
}
}

class CursorSpecialEffects {
constructor() {
this.computerCanvas = document.createElement('canvas')
this.renderCanvas = document.createElement('canvas')

this.computerContext = this.computerCanvas.getContext('2d')
this.renderContext = this.renderCanvas.getContext('2d')

this.globalWidth = window.innerWidth
this.globalHeight = window.innerHeight

this.booms = []
this.running = false
}

handleMouseDown(e) {
const boom = new Boom({
origin: { x: e.clientX, y: e.clientY },
context: this.computerContext,
area: {
width: this.globalWidth,
height: this.globalHeight
}
})
boom.init()
this.booms.push(boom)
this.running || this.run()
}

handlePageHide() {
this.booms = []
this.running = false
}

init() {
const style = this.renderCanvas.style
style.position = 'fixed'
style.top = style.left = 0
style.zIndex = '999999999999999999999999999999999999999999'
style.pointerEvents = 'none'

style.width = this.renderCanvas.width = this.computerCanvas.width = this.globalWidth
style.height = this.renderCanvas.height = this.computerCanvas.height = this.globalHeight

document.body.append(this.renderCanvas)

window.addEventListener('mousedown', this.handleMouseDown.bind(this))
window.addEventListener('pagehide', this.handlePageHide.bind(this))
}

run() {
this.running = true
if (this.booms.length == 0) {
return this.running = false
}

requestAnimationFrame(this.run.bind(this))

this.computerContext.clearRect(0, 0, this.globalWidth, this.globalHeight)
this.renderContext.clearRect(0, 0, this.globalWidth, this.globalHeight)

this.booms.forEach((boom, index) => {
if (boom.stop) {
return this.booms.splice(index, 1)
}
boom.move()
boom.draw()
})
this.renderContext.drawImage(this.computerCanvas, 0, 0, this.globalWidth, this.globalHeight)
}
}

const cursorSpecialEffects = new CursorSpecialEffects()
cursorSpecialEffects.init()

然后在./hexo/source/_data/body-end.swig中添加

1
2
3
4
{# 鼠标点击特效 #}
{% if theme.cursor_effect == "fireworks" %}
<script async src="/js/cursor/fireworks.js"></script>
{% endif %}

next.yml中添加

1
2
# 鼠标点击特效
cursor_effect: fireworks

不蒜子

Next内置了不蒜子统计
next.yml中搜索busuanzi_count并设置为

1
enable: true

自定义单行代码颜色

./hexo/source/_data/styles.styl中添加

1
2
3
4
5
code {
color: #ff511A;
//background: #fbf7f8;
margin: 2px;
}

Live2D看板娘

以我安装的tororo为例,其他模型请见官方文档
安装

1
2
npm install --save hexo-helper-live2d
npm install live2d-widget-model-tororo

next.yml中搜索Progress bar in the top during page loading并设置为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
live2d:
enable: true # 开启Live2D
scriptFrom: local # 插件来源
pluginRootPath: live2dw/ # 插件根目录(相对路径)
pluginJsPath: lib/ # 脚本文件路径(相对于插件根目录路径)
pluginModelPath: assets/ # 模型文件路径(相对于插件根目录)
tagMode: false # 是否标签模式
debug: false # 是否开启调试模式
model:
use: live2d-widget-model-wanko # 选择模型
display:
position: right # 模型在页面上的位置
width: 150 # 模型宽度
height: 300 # 模型高度
mobile:
show: true # 是否在手机端显示
react:
opacity: 1 # 设置模型透明度

Echarts

熊家的可视化图表,与PJAX有冲突,开启PJAX的情况下需要刷新页面才能成功加载。谷歌搜到说要修改PJAX,但是本人水平有限没能成功

安装的插件使用的是4.3,某些图表不能正常显示,需要手动修改为最新的,这个版本失效的话就到ECharts官网上随便打开一个示例,然后用浏览器控制台找到最新js文件的地址替换。

打开./hexo/node_modules/hexo-tag-echarts4/template.html,修改<script src="https://cdn.bootcss.com/echarts/4.3.0/echarts.common.min.js"></script><script src="https://www.echartsjs.com/examples/vendors/echarts/echarts.min.js?_v_=1584687926098"></script>

此外,一些地图类的图表需要引入地图的js,也是开控制台找,然后加入到./hexo/node_modules/hexo-tag-echarts4/template.html中,例如中国地图和世界地图的js

1
2
<script src="https://www.echartsjs.com/examples/vendors/echarts/map/js/china.js?_v_=1584687926098"></script>
<script src="https://www.echartsjs.com/examples/vendors/echarts/map/js/world.js?_v_=1584687926098"></script>

总之就是缺什么补什么

安装

1
npm install hexo-tag-echarts4 --save

使用
400代表图表的高度是400px,85%表示相对宽度是85%,不标明的话默认值是高度400px,宽度81%

1
2
3
{% echarts 400 '85%' %}
\\TODO echarts contents goes here
{% endecharts %}

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{% echarts %}
option = {
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {
type: 'value'
},
series: [{
data: [820, 932, 901, 934, 1290, 1330, 1320],
type: 'line'
}]
};
{% endecharts %}

2022.5.13 已废弃

CDN

Github的服务器在境外,网站加载时间巨长,而使用CDN加速可以有效缓解这一问题

  • 登陆Cloudflare
  • 输入你的域名并点击点击Add site
  • 选择套餐,选free就好
  • 点击Confirm plan
  • Cloudflare会先扫描你的DNS记录,稍等一会会出现你域名现在的解析记录
  • 点击Continue
  • 打开你域名服务商的网站,用Cloudflare给的两个DNS服务器替换掉原来的服务器
  • 完成后回到Cloudflare,点击Done, check nameservers
  • 然后慢慢等待生效,生效后会有邮件提醒
  • 等待的时候可以做一些设置
  • SSL/TLS选项
    • Mode使用默认的Full
    • Always Use HTTPS设置为On
    • Opportunistic Encryption设置为On
    • Authenticated Origin Pills设置为On

填坑完成,毕设期间估计要咕咕咕3个月了┏(^0^)┛

参考: 小丁的个人博客