【博客搭建】将 Butterfly 主题从 git 迁移到 npm 并升级到最新版本
背景
本博客使用的是 Hexo + Butterfly 主题。最初安装主题时,是直接把 butterfly 的源码克隆到 themes/butterfly/ 目录下,然后整体纳入到自己的 git 仓库进行管理。
这种方式有一个很大的问题:主题的数百个文件全部混入了自己的仓库,每次想升级主题时,要么手动 rsync + diff 合并,要么面临覆盖自己修改的风险,非常麻烦。
Butterfly 官方文档推荐的更优方案是:
- 通过 npm 安装主题,主题文件存放在
node_modules/中,不进入自己的 git 仓库 - 将主题配置迁移到 hexo 根目录下的
_config.butterfly.yml文件,与主题代码完全解耦
这样一来,未来升级主题就只需要一条命令 npm update hexo-theme-butterfly,配置文件完全不受影响,非常优雅。
本文记录了从旧的 git 方式迁移到 npm 方式,并同步将 Butterfly 从 5.3.5 升级到 5.5.4 的完整过程。
迁移步骤
第一步:备份当前状态
在开始任何操作之前,先确保当前所有改动已经提交到 git:
1 | cd /home/tianlejin/myblog |
由于整个博客已在 git 管理下,后续任何步骤出问题都可以通过 git checkout 一键回滚。
第二步:创建 _config.butterfly.yml
这是本次迁移的核心步骤。将主题目录下的 _config.yml 内容复制到 hexo 根目录(即 txm_blog/)下:
1 | cp txm_blog/themes/butterfly/_config.yml txm_blog/_config.butterfly.yml |
Hexo 会自动将主题自带的 _config.yml 与根目录下的 _config.butterfly.yml 进行合并,且 _config.butterfly.yml 的优先级更高。从此以后,只需编辑 _config.butterfly.yml 即可,主题目录的 _config.yml 不需要也不应该再修改了。
注意:不要删除主题目录下的 _config.yml,Hexo 的合并机制需要它作为默认值基础。
第三步:保存自定义文件
如果在主题目录下有自定义的 layout 或 css 文件,切记先备份。本博客在主题目录中有两个自定义文件:
themes/butterfly/layout/_custom/photography.pug:相册页面自定义模板themes/butterfly/source/css/_custom/custom.styl:自定义样式
1 | cp -r txm_blog/themes/butterfly/layout/_custom /tmp/butterfly_custom_layout |
第四步:删除旧的主题目录
1 | rm -rf txm_blog/themes/butterfly |
将旧主题目录整体删除,git 会记录这次删除操作。
第五步:通过 npm 安装最新版 Butterfly
在 hexo 根目录下执行:
1 | cd txm_blog |
安装完成后,主题文件位于 txm_blog/node_modules/hexo-theme-butterfly/。由于 node_modules/ 已在 .gitignore 中,这些文件不会进入你的 git 仓库,仓库因此变得非常干净。
可以通过以下命令确认安装的版本:
1 | cat node_modules/hexo-theme-butterfly/package.json | grep '"version"' |
第六步:还原自定义文件
npm 安装方式下,不能直接修改 node_modules/ 里的文件(升级时会被覆盖)。自定义的 layout 和 css 文件需要放到 hexo 主目录下进行管理。
对于 layout 文件,创建对应目录并还原:
1 | mkdir -p txm_blog/layout/_custom |
对于自定义样式文件,放到 source/css/ 目录下:
1 | mkdir -p txm_blog/source/css/_custom |
需要确认 _config.butterfly.yml 中的 inject 配置或相关引用路径指向正确。
第七步:对比新旧配置,补充新增项
主题从 5.3.5 升级到 5.5.4 期间,新增了若干配置项。用 diff 命令查看新版默认配置与你的 _config.butterfly.yml 之间的差异:
1 | diff txm_blog/node_modules/hexo-theme-butterfly/_config.yml \ |
将新版中有而你的配置里没有的项手动添加到 _config.butterfly.yml 中。5.3.5 到 5.5.4 之间主要新增的配置项包括:
nav.display_post_title:导航栏是否显示当前文章标题(5.4.0 新增)google_tag_manager:Google Tag Manager 支持,含tag_id和domain字段(5.4.0 新增)mermaid.open_in_new_tab:在新标签页中打开 Mermaid 图表(5.5.4 新增)mermaid.zoom_pan:Mermaid 图表的缩放和平移支持(5.5.4 新增)structured_data:从布尔值true改为对象格式,含enable和alternate_name字段(5.5.4 新增)lazyload.native:是否使用浏览器原生懒加载代替 vanilla-lazyload(5.5.4 新增)
除了新增项,还有一个格式发生了变化的配置项,如果沿用旧格式会静默失效:
footer.copyright 在 5.4.0 中从布尔值改为了对象格式。旧格式 copyright: true 会导致底部的 Hexo 和 Butterfly 版本信息不显示,需要改为:
1 | footer: |
第八步:测试生成
1 | cd txm_blog |
检查是否有报错,并访问博客确认页面显示正常,重点检查:
- 首页、文章页布局是否正常
- 相册页(使用了自定义 photography.pug)是否正常渲染
- 侧边栏、目录、评论系统是否正常
第九步:提交到 git
确认无误后,提交本次改动:
1 | cd /home/tianlejin/myblog |
可以看到,这次提交会删除大量主题文件(themes/butterfly/ 下几百个文件),同时新增 _config.butterfly.yml 和 layout/_custom/,仓库整体体积大幅缩减。
新版 butterfly 关于 mermaid的 疑似 bug?
升级完成后,使用过程中发现了一个 Butterfly 5.5.4 的 bug,在此记录修复过程。
问题现象:启用 mermaid(mermaid.enable: true)后,博客所有页面底部会出现大段可见的 JS 代码,像乱码一样堆在页脚下方。
根本原因:这是 Butterfly 5.5.4 的 bug,和 Hexo 版本无关,升级 Hexo 也无法解决。新版 mermaid.pug 模板新增了 openSvgInNewTab 函数,该函数里有一段 JS 模板字符串包含字面量 </body></html>,而 Hexo 的 body_end 注入器使用简单字符串匹配查找 </body>,因此注入点落在了 JS 模板字符串内部,导致其后所有 JS 代码以明文渲染到页面上。
需要特别注意的是,将 mermaid.open_in_new_tab 设为 false 并不能解决问题,因为该配置只控制是否显示”在新标签页打开”按钮,而包含 </body> 的 openSvgInNewTab 函数体无论该配置如何设置,都会被完整生成到 HTML 中。
修复方法:直接修改 node_modules/hexo-theme-butterfly/layout/includes/third-party/math/mermaid.pug,将模板字符串中的 </body></html> 拆成字符串拼接,使其不再作为字面量出现:
1 | // 修改前(有 bug) |
由于 node_modules 不进入 git,每次 npm install 后都会丢失这个改动。为此在 patches/postinstall-patch.sh 中保存了补丁脚本,并在 package.json 的 postinstall 钩子中自动执行,确保每次安装依赖后补丁都会被重新应用:
1 | { |
未来升级
完成本次迁移后,以后升级 Butterfly 只需两步:
1 | cd txm_blog |
配置文件完全独立,自定义文件也不在 node_modules/ 里,升级过程不会影响任何自定义内容。
参考资料
- Butterfly 官方文档(快速开始): https://butterfly.js.org/posts/21cfbf15/
- Butterfly GitHub Release: https://github.com/jerryc127/hexo-theme-butterfly/releases
- Hexo 主题配置合并机制: https://hexo.io/zh-cn/docs/configuration#%E4%BD%BF%E7%94%A8%E4%BB%A3%E6%9B%BF%E4%B8%BB%E9%A2%98%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6
