发布于 ,更新于 

Migrate Dream! It's MyHexo!!!!!

缘起

改变

故事还得从某天我登上 WordPress 后台,进行友链维护时的红温说起:

在登入 WP 后台后,没了前台 Cache 的保护,执行与查询操作的时间上升到了惊人的 30s 以上。

经过分析后发现,后端的卡顿和其请求 api.wordpress.org 获取更新应该脱不开干系:国内阿里云到 wp.org 的访问质量本来就差,又因为阿里云 Tailscale 入网把默认的 DNS 炸掉了,一环扣一环下去,请求到 Timeout 也是必然会发生的事件。

而众所周知,PHP 并不是一个特别异步的语言。从上到下依次执行,卡更新就是卡更新了,其他操作站一边等着去。

之前遇到这类事件,我的做法一般是去找个插件或者人工 patch 掉相关请求完事。但也许是红温过了头吧,这次打算直接狠狠心,流浪到下一个博客生成器去。

在小群里求大伙推荐,以及思想斗争后,发现迁移的想法主要基于以下几点:

  • 准备迁移时,原博客所用主题 mdx 已有接近3年没发过新的 release. (尽管写到这里的时候去确认了下,发现居然在三周前发布了 2.0.4 版本,但也只是修复致命 bug 而无新特性更新)
  • 之前写 WordPress 都用 WP-Editor.md 编辑器,中间毕竟还是过了一次 Markdown 到 WP 格式的转换,能找个裸处理 Markdown 内容的当然最好。
  • 主机上的 PHP 旧账负载过于严重,尽量迁移到一个不基于 PHP 的博客系统(Typecho 几年前早就玩过),更极端点,动态生成的比例越少越好,防止给服务器上太大强度。
  • 接触网络安全领域后发现:任何一个欠更新的系统/程序到最后都会变成攻击面。
  • 曾经进入候选圈的有 Ghost,@ruanxingzhi 老师推荐的理由包括 SEO 友好,以及可以根据访问设备的情况自适应资源以保证最优加载速度。以上确实是动态站点独有的优点,也确实没有 PHP 的技术债。但是小溜了一圈后发现,Ghost 还是更想把自己做成一个纯 CMS,官方配套的主题都有一股新闻站风格。(尽管如此,不得不承认还是吊打 WP 默认主题一大圈)
  • 也有群友拿 Mkdocs Material 写博客,但毕竟还是太文档站了一些,少了很多应该有的交互。
  • 群友S:我还是选择静态,db-less 只用拿着一堆 md 想润哪里润哪里就很安心,生成完了也是一堆静态文件随便起个服务器就能跑,能 oob 满足95+%的需求,不能的时候可以自由嵌入 html / js,我觉得在甜点上

综合下来,主流的博客生成器我就知道 Hexo 和 Hugo 两种,考虑到之前还没整过 Hexo 博客,先从 Hexo 开始吧🤪

还有 Astro 什么的高端科技,后续再说。

研究

在 GitHub 上以 hexo theme 为关键词进行搜索,然后按 Recently updated 进行筛选,能够筛选出过去半年到一年还有活跃更新的主题。

我当时筛选出了下面这些:

有些主题落选的原因比较简单:整体设计太过简洁了,有股 Typecho 早期主题的美感。

然后除掉 NexT 这类烂大街的主题,又有很多主题基于 Butterfly 衍生,像 anzhiyu 和 solitude 这类基于 张洪 Heo 设计,美观也是确实美观,但也突出了一个重要问题:这类博客吃封面设计。认真设计的封面和普通随机图的平铺相比,完全就是两个效果,不信的话可以去对比一下 这个演示站

hexo-theme-fluid 秉承了 MD 设计风格,观感上非常像我的旧 mdx 主题;Kratos-Rebirth 成功地复刻了我曾经没买这个域名之前就在用的 Kratos 主题,我也非常喜欢。但毕竟也都有些烂大街了。

到最后,把主题锁定在了 hexo-theme-stellaris ,主要是它的 preview 打开第一眼就惊艳到了我,整体下来就两个字:优雅。属于是小众宝藏主题了。


修改

目前博客在运行的是我的 Fork 版:https://github.com/abc1763613206/hexo-theme-stellaris

主要所做的修改如下:

  • 迁移主体资源到国内 CDN 上
    • 然后中间因为七牛的小插曲 ,目前大部分静态资源暂居国内。
    • 在公共库方面,除了已经死半截的 jsDelivr 和饿了么的 unpkg 镜像,npmmirror 也提供了一个可以直接访问前端文件的接口,在阿里云 CDN 的加持下全球访问速度都比较可观。(尽管因为被大文件滥用开启了审核机制,但已有的白名单足以覆盖大部分前端直接调用的库)
  • 迁移 Waline 到 v3,该修改已提交到上游
  • 同步了上游 gallery 标签和 header 标签
  • 还同步了个视频标签

下面着重说明一下这两个标签:

gallery 标签的使用方法可以参照 上游的介绍 ,但因为和 parse_markdown 功能冲突(解析图片为 img 标签以供 fancybox 等使用,默认启用),于是砍掉了不那么重要的 desc 块,直接在标签内一行一个链接即可,参数部分设定同上游。

使用例:

1
2
3
4
5
6
7
8
9
10
11
12
{% gallery layout:flow %}
https://images.unsplash.com/photo-1565992441121-4367c2967103?w=800&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8NHx8c3BvcnR8ZW58MHx8MHx8fDA%3D
https://images.unsplash.com/photo-1568112505030-08084a1b5215?w=800&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHx0b3BpYy1mZWVkfDh8Ym84alFLVGFFMFl8fGVufDB8fHx8fA%3D%3D
https://images.unsplash.com/photo-1582550945154-66ea8fff25e1?w=800&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHx0b3BpYy1mZWVkfDQyfGJvOGpRS1RhRTBZfHxlbnwwfHx8fHw%3D
https://images.unsplash.com/photo-1703100941710-3b860fa37415?w=800&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8MjcwfHwyMDI0fGVufDB8fDB8fHww
https://images.unsplash.com/photo-1533274221104-015a584a1005?w=800&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHx0b3BpYy1mZWVkfDEzMHxibzhqUUtUYUUwWXx8ZW58MHx8fHx8
https://images.unsplash.com/photo-1702906221006-97bc40420704?w=800&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHw4MXx8fGVufDB8fHx8fA%3D%3D
https://images.unsplash.com/photo-1703081397398-6156621d25ce?w=800&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHw4OHx8fGVufDB8fHx8fA%3D%3D
https://images.unsplash.com/photo-1539604214100-ab860d9082e0?w=800&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHx0b3BpYy1mZWVkfDEzM3xibzhqUUtUYUUwWXx8ZW58MHx8fHx8
https://images.unsplash.com/photo-1634962453938-85e70143f61d?w=800&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHx0b3BpYy1mZWVkfDQ2fGJvOGpRS1RhRTBZfHxlbnwwfHx8fHw%3D
https://images.unsplash.com/photo-1702952084675-b5489e589251?w=800&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHwxMTF8fHxlbnwwfHx8fHw%3D
{% endgallery %}

banner 就没什么好说的,直接参照上游用法就行。

1
2
{% banner abc1763613206 这是个人简介 avatar:https://hanlin.press/images/logo/avatar.png bg:https://images.unsplash.com/photo-1702952084675-b5489e589251?w=800&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHwxMTF8fHxlbnwwfHx8fHw%3D %}
{% endbanner %}

一些其他的事

持续部署与修改时间

静态博客的一个特点是可以在 GitHub 进行同步,然后让 Actions 部署完传上去。

主题的 config 里预留了一个 footer.more ,可以在页面的最下方加一行(设定成字符串),或者再加若干行(设定成字符串数组)。

1
2
3
4
5
6
footer:
more: '我是一行'
# 或者
more:
- '我是第一行'
- '**我是第二行**' # 我修改了下主题让它按 Markdown 解析

利用这个特性可以在博客最下方显示构建信息,我是在 GitHub Actions 中这么设定的:

1
2
3
- name: Generate Footer
run: |
MESSAGEFOOTER="当前博客版本 $(git rev-parse --short=7 HEAD) ,构建于 $(date)" yq -i ".footer.more=strenv(MESSAGEFOOTER)" _config.stellaris.yml

而另一方面,使用 GitHub Actions 每次重新拉取文件,会使文件的修改时间改变,从而导致每次 Hexo 都认为所有文章在构建时都修改了一遍。对于这个问题暂时无解,目前通过在 frontmatter 人工追加一个 updated 解决。

后续的想法

  • 原主题上游还有一些比较好的更新,比如将前端加载的脚本进一步拆分,只在调用到对应标签时才加载;又比如统一图标到一个 icons.yml 中去。这个首先看看原主题作者的适配意愿(毕竟从 ejs 到 jsx 跨了一个技术栈),然后再看看有没有开发余力。
  • 左边栏的目录层级明显是坏的,抽空再看看。
  • Haikei 真的很适合生成背景,本文章头图背景采用这玩意生成。
  • 终究还是走了一遍 鱼塘之乐 的回圈。

upd:醒来拆了一下目录部分的源码,豁然开朗:

本意上是想拿掉 Hexo 内置 tocHelper 的外层 toc 标签再自己套上一层,然后传奇 </ol> 替换高手直接干掉了所有的 </ol> 闭合标签

于是从第一层之后的目录层级全部爆炸,被逆天替换玩法气晕。

html-react-parser 解析一下然后直接取孩子好了,PR 交在了 https://github.com/chiyuki0325/hexo-theme-stellaris/pull/16

另外调试时发现:在 Markdown 中使用跨层级引用(如 h3h5)会直接炸掉 Hexo 自带的 tocHelper,这个问题在向上游贡献前暂时无解。
这也是陈年老问题了,见 https://github.com/hexojs/hexo/issues/2137