又搭博客系统?
Hexo 博客大家都应该比较熟了,使用也比较简单,本地生成下静态文件往 Github 一推就好了,需要的话还可以给 GitHub Pages 配置自定义域名。
但 Github Pages 的访问速度甚是感人,而且 github.io DNS 经常被污染,总之就是不太稳。每次本地构建后推送也显得繁琐。之前刷 GitHub Actions 时发现这玩意做 Github 项目的部署还是很方便的,甚至都不要需要自己的服务器,想着能不能通过 GitHub Actions 将 Hexo 部署到其他地方。
简单来说我们要实现一个通过 CI 自动将 Hexo 博客内容部署到 OSS 的发布系统,其实很简单,往下看~
Hexo 略过
没接触过的同学戳这: hexo.io/zh-cn/
讲下 OSS
姑且贴一下 OSS 的链接 阿里云对象存储服务
日常搬砖中 OSS 使用的比较多,这里以 OSS 作为示例,当然你也可以换成对应的 AWS、七牛云、腾讯云啥的,功能上大差不差。OSS 可以简单的理解成一个网盘,你可在直接在面上传各种媒体与数据文件,然后可以就可以通过生成的资源链接地址访问。
一个静态网站的就是一大堆 html css js 资源整合,正常将这些文件按目录结构上传到 OSS 其实就能访问了,看个最简单的 index.html 文件示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello, World!</title>
</head>
<body>
<h1>Hello, World!</h1>
</body>
</html>
在 OSS 新建一个 Bucket(自定义,名称唯一),然后将 index.html 上传到 OSS 上吧,这里直接上图了:
不过 OSS 有个限制,OSS 本身有提供静态站点的支持需要配置下,否则 html 文件并不能直接在浏览器打开,而是触发了下载,详情可以看这设置静态网站托管。
可以戳这里试试: erii-blog.oss-cn-hangzhou.aliyuncs.com/index.html
出于安全考虑,中国区域自2018年8月13日起,中国以外区域自2019年9月25日起,通过浏览器访问OSS上网页类型文件(mimetype为text/html,扩展名包括HTM、HTML、JSP、PLG、HTX、STM):
- 使用OSS默认域名访问时,Response Header中会自动加上 Content-Disposition:'attachment=filename;'。即从浏览器访问网页类型文件时,不会显示文件内容,而是以附件形式进行下载。
- 使用绑定的自定义域名访问OSS时,Response Header中不会加上 Content-Disposition:'attachment=filename;',只要您的浏览器支持该类型文件的预览,可以直接预览文件内容。
所以咱们需要配置下给 OSS 设置的 Bucket 配置下自定义域名:
设置首页:
设置自定义域名,我这里使用的是 blog.ierii.com,这个域名是在腾讯云上买的(因为便宜!),所以还需要到腾讯云上配置下 CNAM
blog.ierii.com cname erii-blog.oss-cn-hangzhou.aliyuncs.com
然后 OSS 上配置下自定义域名
可以看到首页了~
将 Hexo 资源上传到 OSS
接下来我们看看如何将 Hexo 生成的静态资源上传到 OSS,先初始化个 Hexo 博客项目:
hexo init hexo-oss-action
hexo 默认使用的 yarn 进行依赖安装,不过后面走 GitHub Actions 时我们就直接使用 npm 了,建议初始化项目也使用 npm 安装依赖。
安装完依赖 npm run build 下,看看生产的静态文件:
public
├── 2020
│ └── 12
│ └── 27
│ └── hello-world
│ └── index.html
├── archives
│ ├── 2020
│ │ ├── 12
│ │ │ └── index.html
│ │ └── index.html
│ └── index.html
├── css
│ ├── fonts
│ │ ├── FontAwesome.otf
│ │ ├── fontawesome-webfont.eot
│ │ ├── fontawesome-webfont.svg
│ │ ├── fontawesome-webfont.ttf
│ │ ├── fontawesome-webfont.woff
│ │ └── fontawesome-webfont.woff2
│ ├── images
│ │ └── banner.jpg
│ └── style.css
├── fancybox
│ ├── jquery.fancybox.min.css
│ └── jquery.fancybox.min.js
├── index.html
└── js
├── jquery-3.4.1.min.js
└── script.js
这么多文件都要一个个手动往 OSS 上怼也是不现实的,OSS 有提供各种环境的 SDK,这里这里咱们直接上 node sdk,安装依赖:
npm i ali-oss recursive-readdir -D
recursive-readdir 是个工具库用于获取目标文件夹下的所有文件路径。
ali-oss 的基本用法也很简单:
const OSS = require('ali-oss');
const client = new OSS({
region: 'oss-cn-hangzhou', // 创建 bucket 选择的区域
bucket: 'erii-blog', // 创建 bucket 名称
accessKeyId: '***', // 你的 accessKeyId
accessKeySecret: '***', // 你的 accessKeySecret
});
// 将 public/index.html 上传到 erii-blog bucket 根目录下的 hexo-index.html
client.put('hexo-index.html', './public/index.html').then(res => {
console.log(res.url);
// http://erii-blog.oss-cn-hangzhou.aliyuncs.com/hexo-index.html
});
accessKeyId 与 accessKeyId 可以在这获取:
上传完成可以在 OSS 控制台看到 hexo-index.html
接下只要写个脚本将 publish 目录下的所有文件都按照对应的路径上传到 OSS 就行了,实现也比较简单这里直接贴代码了:
// upload.js
const OSS = require('ali-oss');
const recursive = require('recursive-readdir');
const ORIGIN = 'http://blog.ierii.com';
const PUBLISH_PATH = './public';
const client = new OSS({
region: 'oss-cn-hangzhou', // 创建 bucket 选择的区域
bucket: 'erii-blog', // bucket name
accessKeyId: '***', // 你的 accessKeyId
accessKeySecret: '***', // 你的 accessKeySecret
});
function getFiles() {
return new Promise((resolve, reject) => {
recursive(PUBLISH_PATH, (err, files) => {
if (!err) {
resolve(files);
} else {
reject(err);
}
});
});
}
function upload(file) {
return client.put(file.replace('public/', ''), `./${file}`).then(res => {
const url = `${ORIGIN}/${res.name}`;
console.log(`SYNC SUCCESS: ${url}`);
return url;
});
}
(async function main() {
const files = await getFiles();
const uploadTasks = files.map(file => upload(file));
await Promise.all(uploadTasks);
})();
再打开 blog.ierii.com 发现 hexo 生产的静态文件都已经同步到 OSS 了,接下我们只需要考虑如何将这些操作通过 CI 实现自动化部署。
通过 GitHub Actions 实现自动部署
总之先把之前创建的 Hexo 项目先推送到 Github 上去吧。
关于 GitHub Actions 的教程建议可以看下官方文档和阮一峰的老师文章 GitHub Actions 入门教程 。
与 GitLab CI、Travis CI 不同的是 GitHub Actions 功能是建立在一个个 action 之上的,官方已经提供需要方便好用的 action,针对环境的部署与配置会比 GitLab CI 和 Travis CI 方便很多。下面直接上手好理解点。
在当前目录底下新建一个 .github/workflows/main.yml 的配置文件:
touch .github/workflows/main.yml
这是 GitHub Actions 默认读取的配置文件目录,main.yml 配置如下:
name: hexo-oss-action
on: [push] # 当有新 push 时触发
jobs:
build: # 一项叫做 build 的任务
runs-on: ubuntu-latest # 在最新版的 Ubuntu 系统下运行
steps:
- name: Checkout # 将仓库内 master 分支的内容下载到工作目录
uses: actions/checkout@v2 # 脚本来自 https://github.com/actions/checkout
- name: run node # 配置 Node 环境
uses: actions/setup-node@v1 # 配置脚本来自 https://github.com/actions/setup-node
with:
node-version: '12'
- run: npm install
- run: npm run build
- run: node sync.js
env:
OSS_REGION: ${{ secrets.OSS_REGION }}
OSS_BUCKET: ${{ secrets.OSS_BUCKET }}
OSS_ACCESS_KEY_ID: ${{ secrets.OSS_ACCESS_KEY_ID }}
OSS_ACCESS_KEY_SECRET: ${{ secrets.OSS_ACCESS_KEY_SECRET }}
ORIGIN: ${{ secrets.ORIGIN }}
配置文件非常好理解,push 触发 CI 任务,runs-on: ubuntu-latest 指定系统环境,steps 的步骤清楚的描述了构建流程:
- 使用 actions/checkout@v2 将仓库内容下载到工作目录
- 使用 actions/setup-node@v1 配置 node 环境
npm install安装依赖npm run buildhexo buildnode sync.js同步 publish 目录下的静态内容到 OSS
这里需要关注下 env 中的环境变量配置,日常开发中有许多私密的配置是不能直接在代码中硬编码的,像上是面的 OSS 的 accessKeyId 和 accessKeySecret 一类的配置直接暴露出来是很危险的。我们需要一个更加安全方法将配置信息传递给 CI 环境,GitHub Actions 中我们可以直接在 CI 中通过 env 项获取当前项目的 secrets 配置,secrets 直接在项目 Github Setting 中配置,十分方便:
然后看下关键的 sync.js:
// sync.js
const OSS = require('ali-oss');
const recursive = require('recursive-readdir');
const PUBLISH_PATH = './public';
// 从 Github Secrets 中获取配置
const {
OSS_REGION,
OSS_BUCKET,
OSS_ACCESS_KEY_ID,
OSS_ACCESS_KEY_SECRET,
ORIGIN,
} = process.env;
const client = new OSS({
region: OSS_REGION,
bucket: OSS_BUCKET,
accessKeyId: OSS_ACCESS_KEY_ID,
accessKeySecret: OSS_ACCESS_KEY_SECRET,
});
function getFiles() {
return new Promise((resolve, reject) => {
recursive(PUBLISH_PATH, (err, files) => {
if (!err) {
resolve(files);
} else {
reject(err);
}
});
});
}
function upload(file) {
return client.put(file.replace('public/', ''), `./${file}`)
.then(res => {
const url = `${ORIGIN}/${res.name}`
console.log(`SYNC SUCCESS: ${url}`);
return url;
});
}
(async function main() {
const files = await getFiles();
await Promise.all(files.map(file => upload(file)));
console.log('SYNC DONE !');
})();
和上面的 upload 没啥差别只是将一些配置挪到了 Github Secrets 中,这里需要强调下 CI 运行的目录就是当前项目的根目录在 sync.js 不需要做啥目录切换的操作,现在我们需要将本地修改推送到 Github 就可以看到 Github Actions 的构建了。
至此一个简单的 Hexo 博客发布系统就完成了~
当然 Github Actions 还可以实现更多强大的功能,有兴趣的小伙伴可以深入研究下,这里只是抛个小小实践思路。
其他
OSS 好像不能白嫖,需要花个 4 块还是 7 块大洋开通下,自己玩玩还是很便宜的~
OSS 配置完自定义域名后如果未配置证书默认走的 http 协议,有需要的同学可以通过配置证书托管为自定义域名加上 https 小绿标:
我的域名证书是直接通过腾讯云的免费证书生成的,有兴趣的同学也可以捣鼓下 Let's Encrypt
演示的仓库地址在这: github.com/kinglisky/h…
最后贴个喜欢的漫画:
嘻嘻~