jekyll 迁移至 hexo
2021 年之后工作忙的飞起,却又无事足道。趁着国庆假期,折腾了一下博客,将原来的 jekyll
替换为了 hexo
。期间踩了一些坑,以下仅以记录。
更换原因
回想起迁移的原因,突然间竟觉得有些复杂。最初 jekyll
用的好好的,从写作到发布的流水线也跑的比较顺,如果不是闲的蛋疼,断然是没有更换的必要。只不过原来的 jekyll
版本中一直含有「暗伤」,即:评论功能要使用科学上网工具才能使用。之前也找过一些方案,大致思路是使用一个反向代理来访问 disqus
的 API
。具体的实现方案,网上各有所表,始终不能满足自己的需求。
这两天得闲,又在网上搜索起来,发现了 DisqusJS 这个方案,使用起来好像也挺简单,反向代理的代码别人也提供了 disqusjs-proxy-vercel, 正巧我也在使用 vercel,那就折腾一下呗。
仔细看了一下说明文档,顺带访问了使用案例中的几个博客。嗨,怎么都是 「Powered by Hexo」呢?回头再看看自己的 jekyll
博客,虽然主题用的是高仿 「Next」(Hexo 上的著名主题),可想改改前端模板部分,居然感觉无从下手。再想想当初搞 jekyll
折腾 Ruby
的过往,索性换成 Nodejs
的 Hexo
算了, 就算出了什么岔子,大概率也不用从头学起,现代前端的 node、npm 总还是知道在什么地方找问题的。
操作步骤
按照比较正统的工程做法应该是:
- 备份数据
- 创建新的站点
- 迁移数据
- 上线新的站点
- 域名记录变更
- 下线旧站点
这套工程实践没太大问题,而且对于风险也有较好的应对方案,比如万一搞砸了,还可以反向执行一遍回滚到原来的状态。可是,毕竟手头没有那么多宽裕的资源和时间,直接更新算了。所以大致分为以下几步:
- 打开冰箱门
- 把大象塞进冰箱
- 把冰箱门关上
说人话就是:
- 在原来的站点上直接改代码
- 把新的代码更新上线,直接替换旧的站点
这样考虑基于:
- 个人博客没有什么用户数据,文章数据就是代码,在 Git 仓库中有版本记录
- 要搞多个生产环境,域名记录变更都有时间开销,直接代码更新花的时间更少
本地环境搭建
按照 Hexo官方的说明 对于熟悉 npm
的进阶用户,可以执行
1 | $ npm install hexo |
然后通过
1 | $ npx hexo <command> |
或把 node_modules
的 hexo
加入环境变量后使用
1 | $ hexo <command> |
这两个我都试了,并没有什么用。直到我按照常规方法在 package.json
中添加了 scripts
来做了 npm run
的映射,才可以通过
1 | $ npm run hexo <command> |
进行使用
为了不这么恶心,干脆做回小白用户全局安装了 hexo
1 | $ npm i hexo -g |
为了测试效果,我还是在 package.json
中添加了几个 scripts
1 | { |
按照 Hexo官方的说法,我就只需要拷贝一下 _posts
里的文件就行了。
直接 yarn run server
后,除了一堆报错,并没有什么效果。开了一个全新的 hexo
项目跑了一下,才明白首先要执行 hexo init
命令,于是我又屁颠屁颠的执行了 hexo init
。继续报错,大意是: 文件夹不是空的,没办法初始化。
此时进入了逻辑黑洞,初始化就得是全新的开始,迁移就肯定不是空白的项目,但是要迁移之后能运行,又得执行初始化命令。这不是死局了吗? 又查看了一下Hexo文档,手动将 Hexo
所需的文件都建好,再把原来的 jekyll
的文件删个七七八八,终于生成成功。
分支合并
为了以防万一,前面的所有操作都在一个新开的分支 Hexo
上完成,最后则利用 Github
的 Pull Request
合并至主分支上并完成部署。由于之前的博客使用了 vercel
部署,新建 Pull Request
会触发 vercel
的构建,构建通过后才进行真正的合并操作。到此时为止,一切都那么顺利。
设置主题
Hexo
的默认主题是 landscape,我还是想换回 「原版」的 Next
。继续按照 Next的官方文档 的说法,直接进入博客目录
1 | $ git clone https://github.com/theme-next/hexo-theme-next themes/next |
然后再把博客的 _config.yml
中的 theme
改为 next
。 官方还提供了几种方式,比如直接下载文件,下载指定文件之类的。为了方便,不纠结直接用官方默认推荐的吧。
令人感到困惑不已的是,
Next
在Github
上居然有两个仓库,一个是 theme-next,一个是 next-theme。theme-next
提供了npm
安装的方式, 而next-theme
则没有。当然这些都是事后发现的,官方的Github
并没有更新有关文档,而是写在了 官方站点的文档 里。
集成好了主题之后预览,发现和原来的主题还是不一样。查了下资料发现 Next
主题分成了几种 Scheme
:
- Muse
- Mist
- Pisces
- Gemini
原先博客用的正是其中的 Pisces
,可是要去哪里修改这个配置呢?博客的主题配置项内并没有相关设置。自己观察一下,themes/next
下居然也有一个 _config.yml
,把里面的 Scheme
修改一下:
1 | # Schemes |
其他七七八八的设置,也按网上找的一个 文档 改改。
还是不要随便找个文档看,官方文档 还是所有文档里最靠谱的
此时,本地预览一切正常。我主要进行了以下操作
迁移文章
迁移文章很简单,直接把原来的 _posts
文件拷贝到 source/_posts
即可。我的博客带着沉重的历史,所以每个 .md
里都有一个 permalink
,且原来的 permalink
都不会带有后缀 .html
,我尝试设置了博客的 _config.yml
中的
1 | pretty_urls: |
发现无论怎么设置,产生的文件都不会带有 .html
后缀,这就导致直接浏览器预览的时候无法正常打开页面,而是直接下载文件。不浪费时间,索性一把梭把所有 .md
中的 permalink
都删除。 具体方法是使用 VSCODE
的全局搜索功能,搜索 _posts
文件夹下所有文件,并打开正则模式,搜索 permalink: (.*)
全部替换为 「空」 即可。
迁移页面
原来的博客里除了博文之外,还有「关于」、「标签」、「实验室」几个页面,这部分 Hexo
和 jekyll
非常类似,只要在 source
下建立对应的文件夹,并放入一个 index.md
,写好 Front Matter
即可。
比如「关于」页面,就在 source
下建立一个 about
文件夹,里面放一个 index.md
文件,内容为
1 | --- |
还原功能
最主要的数据迁移完成之后,开始还原原来博客的功能。所有的 jekyll
下面有的,Hexo
都支持。
侧边菜单
在 themes/next/_config.yml
查找 menu
,把它改成自己要的:
1 | menu: |
其中「搜索」菜单是打开本地搜索自动增加的,所以这里不用设置
menu
下的每一项代表一个菜单,前面的 key
代表菜单名, 后面的 value
分为两部分。||
前的是路径,||
后的是图标。看名字就知道使用的是 font-awesome
字体图标库,所用图标标识出门左转去 fontAwesome 找吧。
i18n
菜单改完,预览都是英文的,设置 _config.yml
里的 language
为 zh-Hans
,还是英文的。进入 themes/next/languages
一看,原来这里的文件是 zh-CN.yml
。这就对不上啊,改成 zh-Hans.yml
后搞定。因为我自己的 menu
里加了点东西,所以这里在多语言文件里也加上对应的。
Next 官方在 6.0 以上版本特意的把
zh-Hans
改成了zh-CN
Google Analytics
在 themes/next/_config.yml
查找 google_analytics
, 把 tracking_id
填上 UA-********-*
这样的值即可,和原来 jekyll
差不多。
Disqus
在 themes/next/_config.yml
查找 disqus
,enable
填 true
, shortname
填注册的 disqus
用户名。在搜索 disqus
发现有 disqusjs
的设置,前面说过,要用起来需要搭建反向代理,以后再说吧。
Latex
我的个别几篇文章里面用到了公式,所以需要开启。Next
里面提供 Mathjs
和 KaTex
两种方案,官方也给出了说明对比。折腾了一下发现太麻烦,得修改原来书写公式的方式,而且都会在前端额外注入 js
。误打误撞发现了 hexo-filter-mathjax,使用的是服务端方式,也就是说在构建时就直接生成了公式,这岂不美哉?用之!
凡事有得必有失,使用这个插件后, 1. 需要将 Hexo
的渲染器改为 hexo-renderer-pandoc 2. 需要将 Next
的 math.mathjax.enable
和 math.katax.enable
统统设置为 false
3. 需要在用到公式的博客的 Front Matter
里添加 mathjax: true
还好,这些都是小事。
安装插件:
1 | $ yarn add hexo-filter-mathjax |
换渲染器:
1 | $ yarn remove hexo-renderer-marked |
全套搞完之后,本地预览公式正常,和原来一模一样。
该插件依赖了
pandoc
,导致在vercel
构建栽了跟头,此处不表,后面详述。
fancyBox
预览时发现图片直接都显示出来,点击没有放大效果,原来 jekyll
主题里这一部分是通过 fancyBox
实现了,这里应该也类似。 在 themes/next/_config.yml
查找 fancybox
,设置为 true
。
本地搜索
在 themes/next/_config.yml
查找 local_search
,把 enable
设置为 true
,这样菜单里的最后一项将会多出一个 「搜索」,点击「搜索」,熟悉的搜索弹窗出现了。
自动摘要截断
按照官方的说明,在 themes/next/_config.yml
设置了 excerpt_description
为 true
,并没有什么用。Next
官方在某个版本里删除了这个功能,意不意外,惊不惊喜? 按照官方的推荐,安装 hexo-excerpt
1 | $ yarn add hexo-excerpt |
然后配置博客 _config.yml
,根据我自己的需求,我改成了这样
1 | excerpt: |
新增功能
字数统计和阅读时长
看到别人博客里有本文多少字,大约需要多少分钟读完,发现也支持了,具体使用 hexo-symbols-count-time 插件。首先先安装
1 | $ yarn add hexo-symbols-count-time |
然后在博客的 _config.yml
里添加:
1 | symbols_count_time: |
DisqusJS
正如前文所言,先按照 disqusjs-proxy-example 中的方法搭建反代,直接用 vercel
部署好,将部署完成后的域名填写到 themes/next
的 disqusjs
部分里即可完成。此处直接按 disqusjs 文档 操作即可.
提交修改
本地预览一切就绪,准备提交到远程的 Github
,让 vercel
部署。然而,提交不了了。想了一下,问题就出在最开始提到的 Next
主题安装环节。本来的博客属于一个 Git
仓库,里面又克隆了 Next
主题的仓库。对主题配置的修改都在主题仓库里,那提交到哪里去?提交到 Next
官方的仓库吗?
按照现代前端的逻辑,安装的应该是个 npm
包啊,而且大概率不会去修改 node_modules
里的东西。事已至此,看看怎么处理吧。 即然不可能提交到 Next
官方仓库,那么我们就把官方仓库 Fork
一份出来呗。然后通过 git remote
的命令把 themes/next
的远端仓库设置为我自己的 Fork
出来的仓库地址。
现在有了两个仓库,这两个仓库管理原则上是独立的,凭啥博客的仓库会更新和纳入主题的仓库内容呢?Git Submodule
即时登场,利用 git submodule add
把 themes/next
作为子模块加入了博客仓库。提交、推送这些常规操作都可以完成了。然后在 Github
里创建一个新的 Pull Request
,开始发布前预构建。
vercel 部署
构建模板修改
第 1 次构建失败,错误出现在构建完成时
1 | No Output Directory named "_site" found after the Build completed. |
这是因为忘记了修改 vercel
的构建模板,在 vercel
的 Settings
面板下的 Build & Development Settings
中,把原来的模板 jekyll
修改为 Hexo
。
手动安装 Pandoc
第 2 次至第 N 次,打包一开始就报 ERROR
,一直报
1 | pandoc exited with code null. |
查了资料,有文章说是因为博客里面包含引号导致,解决方案是卸载。这?这?这是自断一臂吗?继续查继续试,最后发现是因为 vercel
的构建环境里压根没有 pandoc
啊,预装列表 别人写好了。那我自己装吧,又找到了 一篇文章 说是自己把 Pandoc
的安装包从 deb
转为 rpm
, 然后上传到自己的仓库里再用构建命令调用。这?不应该吧?继续找,又找到了一篇时间较近的文章,而且名字一看就相当靠谱 Running a Pandoc build on Vercel,按照文章说的,自己在博客仓库内建一个 build.sh
,内容为
1 | yum install wget |
在 vercel
的 settings
面板中找到 Build Command
打开 OVERRIDE
开关,输入 sh ./build.sh
之后保存,终于构建成功。
修改 submodule 的 url
构建开始时,始终会报获取 submodule
失败
1 | Warning: Failed to fetch one or more git submodules |
原因是 vercel
不支持 ssh
协议的 url
, 之前有人遇到过,改为 https
即可修复。当然这样的话,仓库地址必须是公开的,有一定的安全风险。如果想要使用私有仓库,则可以参考 Vercel private submodule 中的方法