这是一篇基础教程,简单的搭建hexo博客

前言

hexo也算是老牌博客框架了,以前对于hexo的了解也仅仅停留在知道他是一个能够快速将本地的markdown文件生成静态网站的框架。
最早的个人博客网站还是自己动手,从0-1的一个spa,并做了大量seo,设备适配,性能优化,配套开发的服务也包括后台管理系统,node服务以及sql数据库,当然个人还兼备产品设计,UI设计等工作。

入坑尝试hexo是由于看到hexo:

  1. 主题丰富,且多端适配良好。
  2. seo优化,网页性能👍🏻。
  3. 方便管理,迁移。

安装

准备好基本环境:

  1. git
  2. node

直接全局安装hexo-cli

1
npm install -g hexo-cli

运行检查是否安装完成

1
hexo version

cmd快速辅助工具

有效的快速开启服务关闭服务,避免每次都输入命令的繁琐

初始化项目

使用hero-cli初始化blog项目,我取名叫”luna”吧🌛。

1
hexo init luna

接着安装依赖

1
2
cd luna
npm install

安装完成之后,我们可以运行看下效果。

1
hexo s

打开http://localhost:4000/查看效果

image-20220703154230288

文章迁移

把原先写过的markdown,copy到source/_posts。

1
cp -r /Users/allen/Documents/blog /User/allen/Desktop/luna/source/_posts

这里我没找到如何快速批量配置front-matter的方式,只能手动一个一个改了

配置_config.yml

Yaml语言的配置文件,对网站进行详细的设置。

https://hexo.io/docs/configuration.html

安装主题

默认的主题有点丑,可以到官网找下喜欢的。

https://hexo.io/themes/

我选了Butterfly
https://butterfly.js.org/

按照提示安装配置即可。

写个web服务器

目前我们已经完成了hexo项目的初始化,但hexo仅是一个静态页面生成的框架,如果我们需要部署到机器上,那么还需要一个服务器。

express即可满足我所有需求。

安装express,在项目根目录下,创建一个luna/www/index.js

1
2
3
4
5
6
7
8
9
10
const express = require('express')
const app = express()
const port = 80

/** 静态资源 */
app.use(express.static('./public'))

app.listen(port, () => {
console.log(`app listening on port ${port}`)
})

安装pm2,添加script。

1
2
3
4
5
"scripts": {
"logs": "pm2 logs",
"start": "pm2 start ./www/index.js",
"stop": "pm2 stop all"
}

其实快速在机器上更新代码还挺麻烦的,再写个脚本。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
echo "🚚 拉取最新代码..."
git pull

echo "🚗 更新npm包..."
npm install

echo "📦️ 打包前端代码..."
npm run build

echo "🌏︎ 启动www服务..."
npm run stop
npm run start

echo "🎉🎉🎉 部署成功!!!"

放在luna/script/deploy.sh,然后再加个script。

1
2
3
4
5
6
"scripts": {
"logs": "pm2 logs",
"start": "pm2 start ./www/index.js",
"stop": "pm2 stop all",
"deploy": "sh ./script/deploy.sh"
}

测试一下。

1
npm run deploy

image-20220721230920045

看起来好像没什么问题🤔

搭个图床

博客里图片资源那么多,你看我的1M的学生服务器怎么扛得住呢?图片资源都上CDN吧。

本身我也习惯本地用Typora写博,那么就推荐一下picGo做图床管理吧,mac体验满分。

image-20220721231448819

PicGo官网

支持的图床还蛮多的(我用COS),先配置好你的图床。image-20220721231557705

打开Typora偏好设置,配置PicGO自动上传。

image-20220721231756498

试试在Typora里粘贴图片吧

实现自动部署

自动部署使用方式我写进了仓库的README.md了

自动部署

100行实现

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
const dotenv = require("dotenv")
dotenv.config()

const { Buffer } = require('buffer');
const childrenProcess = require('child_process')
const bodyParser = require('body-parser')
const crypto = require('crypto');
const express = require('express')
const app = express()
const port = 80
const HUB_SECRET = process.env.HUB_SECRET;

app.use(bodyParser.json())

/** 执行命令 */
const exec = (bash) => {
console.log(`🔧 开始执行命令 ${bash}`)
return new Promise((resolve, reject) => {
childrenProcess.exec(bash, (error, stdout, stderr) => {
if (error) {
console.error(`🔧 命令出错 ${bash} exec error: ${error}`);
reject()
return
}
console.log(`🔧 命令完成 ${bash} stdout: ${stdout} stderr: ${stderr}`);
resolve()
})
})
}

/** 校验sig */
const validateHubSig = (req) => {
try {
if (!req.body) return false
const signature = Buffer.from(`sha1=${crypto.createHmac('sha1', HUB_SECRET).update(JSON.stringify(req.body)).digest('hex')}`)
const _signature = Buffer.from(req.headers['x-hub-signature'])
if (signature.length !== _signature.length) {
return false
}
return crypto.timingSafeEqual(signature, _signature)
} catch (error) {
console.error('validateHubSigFail', error)
return false
}
}

/** 静态资源 */
app.use(express.static('./public'))

/** webhook - 自动刷新 */
app.post('/refresh', (req, res) => {
if (validateHubSig(req)) {
console.log('🏂 webhook自动刷新触发,正在执行...')
exec('git pull')
.then(exec.bind(this, 'npm install'))
.then(exec.bind(this, 'npm run build'))
.then(() => {
console.log('🎉 自动刷新完成!')
}).catch(() => {
console.log('❌ 自动刷新失败,请查看日志详情!')
})
res.status(200).send({
msg:'webhook success'
})
}
res.status(400).send({
msg: 'validate signature fail'
});
})

app.listen(port, () => {
console.log(`app listening on port ${port}`)
})

剩下就是直接push,再也不用上机器了(当然有BUG还是要去的 😅)