3

网站切换到 Hexo

 2 years ago
source link: https://mritd.com/2020/10/08/switch-jekyll-to-hexo/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

一、Hexo 安装

Hexo 安装根据官方文档直接操作即可,安装前提是需要先安装 Nodejs(这里不再阐述直接略过)

npm install -g hexo-cli

Hexo 命令行工具安装完成后可以直接初始化一个样例项目,init 过程会 clone https://github.com/hexojs/hexo-starter.git 到本地,同时自动安装好相关依赖

# mritd.com 为目录名,个人习惯直接使用网站域名作为目录名称
hexo init mritd.com

进入目录启动样例站点

# 进入目录
cd mritd.com
# 启动本地服务器进行预览
hexo serve

二、主题设置

基本的样例博客启动完成后就需要选择一个主题,主题实质上才决定博客功能,这里目前使用了 Fluid 主题,这个主题目前兼具了个人博客所需的所有功能,而且作者提交比较活跃,文档也比较全面。

# 下载主题
git clone https://github.com/fluid-dev/hexo-theme-fluid.git themes/fluid
# 切换到最新版本
(cd themes/fluid && git checkout -b v1.8.3 v1.8.3)

接下来修改 _config.yml 配置切换主题即可

# Extensions
## Plugins: https://hexo.io/plugins/
## Themes: https://hexo.io/themes/
theme: fluid

然后重新启动博客进行预览: hexo cl && hexo s

关于主题其他配置可自行阅读 官方文档,文档有时可能更新不及时,可同时参考仓库内的 _config.yml 配置。

三、文章导入

关于 jekyll 博客的文章如何导入到 Hexo 中网上有很多脚本;但是实际上两个静态博客框架都是支持标准的 Markdown 语法书写的文章进行渲染,唯一区别就是每篇文章上的 “头”。

---
catalog: true
categories:
  - [Kubernetes]
  - [Golang]
date: 2018-11-25 11:11:28
excerpt: 最近在看 kubeadm 的源码,不过有些东西光看代码还是没法太清楚,还是需要实际运行才能看到具体代码怎么跑的,还得打断点 debug;无奈的是本机是 mac,debug 得在 Linux 下,so 研究了一下 remote debug
keywords: kubeadm,debug
multilingual: false
tags:
  - Golang
  - Kubernetes
title: 远程 Debug kubeadm
index_img: img/remote_debug.jpg
---

具体文章内容......

所以直接复制 jekyll 的 md 文件到 source/_posts 目录,并修改文档头部即可。

四、自动更新

目前博客部署在自己的 VPS 上,以前都是将博客生成的静态直接使用 nginx 发布出去的;但是面临的问题就是每次博客更新都要手动去 VPS 更新,虽然可以写一些 CI 脚本但是并不算智能;得益于 Golang 官方完善的标准库支持,这次直接几行代码写一个静态服务器,同时拦截特定 URL 来更新博客:

package main

import (
	"fmt"
	"net/http"
	"os"
	"os/exec"
	"path"
)

func main() {
	http.Handle("/", fileServerWithCustom404(http.Dir("/data")))
	http.HandleFunc("/update", update)

	fmt.Println("Updating WebSite...")
	_, err := gitPull()
	if err != nil {
		fmt.Printf("WebSite update failed: %s", err)
	}

	fmt.Println("HTTP Server Listen at [:8080]...")
	_ = http.ListenAndServe(":8080", nil)
}

// POST 请求 /update 触发 git pull 更新博客
func update(w http.ResponseWriter, r *http.Request) {
	if r.Method != http.MethodPost {
		w.WriteHeader(http.StatusBadRequest)
		_, _ = w.Write([]byte("only support POST method.\n"))
		return
	}
	bs, err := gitPull()
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
		_, _ = w.Write([]byte(err.Error()))
		return
	}
	w.WriteHeader(http.StatusOK)
	_, _ = w.Write(bs)
}

// 包装一下 404 状态码,返回自定义的 404 页面
func fileServerWithCustom404(fs http.FileSystem) http.Handler {
	fsh := http.FileServer(fs)
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		_, err := fs.Open(path.Clean(r.URL.Path))
		if os.IsNotExist(err) {
			r.URL.Path = "/404.html"
		}
		fsh.ServeHTTP(w, r)
	})
}

func gitPull() (msg []byte, err error) {
	cmd := exec.Command("git", "pull")
	cmd.Dir = "/data"
	return cmd.CombinedOutput()
}

五、Docker 化

有了上面的静态服务器,写个 Dockerfile 将 Hexo 生成的静态文件打包即可:

FROM golang:1.15-alpine3.12 AS builder

ENV GO111MODULE on

COPY goserver /go/src/github.com/mritd/hexo/goserver

WORKDIR /go/src/github.com/mritd/hexo/goserver

RUN set -e \
    && go install

FROM alpine:3.12 AS dist

LABEL maintainer="mritd <[email protected]>"

ENV TZ Asia/Shanghai
ENV REPO https://github.com/mritd/mritd.com.git

COPY --from=builder /go/bin/goserver /usr/local/bin/goserver

RUN set -e \
    && apk upgrade \
    && apk add bash tzdata git \
    && git clone ${REPO} /data \
    && ln -sf /usr/share/zoneinfo/${TZ} /etc/localtime \
    && echo ${TZ} > /etc/timezone \
    && rm -rf /var/cache/apk/*

WORKDIR /data

CMD ["goserver"]

镜像运行后将使用 /data 目录最为静态文件目录进行发布,Hexo 生成的静态文件(public 目录)也会完整的 clone 到当前目录,此后使用 POST 请求访问 /update 即可触发从 Github 更新博客内容。

六、Travis CI 集成

所有就绪以后在主仓库增加 .travis.yml 配置来联动 travis ci;由于每次 push 到 Github 的内容实际上已经是本地生成的 public 目录,所以 CI 只需要通知服务器更新即可;强迫症又加了一个 Telegram 通知,每次触发更新完成后 Telegram 再给自己推送一下:

language: go

git:
  quiet: true

script:
- curl -X POST ${CALLBACK}

after_script:
- curl -X POST https://api.telegram.org/bot${TELEGRAM_TOKEN}/sendMessage -d chat_id=${TELEGRAM_CHAT_ID} -d "text=mritd.com deployed."

七、gulp 优化

由于目前一些配图啥的还是存储在服务器本地,所以图片等比较大的静态文件仍然是访问瓶颈,这时候可以借助 gulp 来压缩并进行优化:

# 安装 gulp
npm install -g gulp
# 安装 gulp 插件
npm install gulp-htmlclean gulp-htmlmin gulp-minify-css gulp-uglify-es gulp-imagemin --save
# 重新 link 一下
npm link gulp

接下来编写 gulpfile.js 指定相关的优化任务

var gulp = require('gulp');
var minifycss = require('gulp-minify-css');
var uglify = require('gulp-uglify-es').default;
var htmlmin = require('gulp-htmlmin');
var htmlclean = require('gulp-htmlclean');
var imagemin = require('gulp-imagemin');

// 压缩html
gulp.task('minify-html', function() {
    return gulp.src('./public/**/*.html')
        .pipe(htmlclean())
        .pipe(htmlmin({
            removeComments: true,
            minifyJS: true,
            minifyCSS: true,
            minifyURLs: true,
        }))
        .pipe(gulp.dest('./public'))
});

// 压缩css
gulp.task('minify-css', function() {
    return gulp.src('./public/css/*.css')
        .pipe(minifycss({
            compatibility: '*'
        }))
        .pipe(gulp.dest('./public/css'));
});

// 压缩js
gulp.task('minify-js', function() {
    return gulp.src('./public/js/*.js', '!./public/js/*.min.js')
        .pipe(uglify())
        .pipe(gulp.dest('./public/js'));
});

// 压缩图片
gulp.task('minify-images', function() {
    return gulp.src('./public/img/*.*')
        .pipe(imagemin(
        [imagemin.gifsicle({'optimizationLevel': 3}),
        imagemin.mozjpeg({'progressive': true}),
        imagemin.optipng({'optimizationLevel': 7}),
        imagemin.svgo()],
        {'verbose': true}))
        .pipe(gulp.dest('./public/img'))
});

// 默认任务
// 这里默认没有运行 minify-js,因为我发现 js 压缩以后 PageSpeed 评分
// 莫明其妙的降低了,目前只优先考虑桌面浏览器的性能,暂不考虑移动端
gulp.task('default', gulp.parallel(
    'minify-html','minify-css','minify-images'
));

最后在每次部署时执行一下 gulp 命令即可完成优化: hexo cl && hexo g && gulp


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK