最近对博客进行了一次较大规模的更新,将整个系统从 Hexo 6 升级到了 Hexo 7,同时升级了 Butterfly 主题和相关依赖包。这个过程中遇到了不少问题,还有碰巧遇到stylus乌龙事件,在此记录整个更新过程和解决方案。

更新概览

本次更新涉及的主要组件:

  • Hexo 框架:6.3.0 → 7.3.0
  • Butterfly 主题:升级到最新版本
  • Node.js 环境:16 → 18
  • 数学公式支持:配置 MathJax
  • 图表支持:配置 Mermaid

问题1:GitHub Actions 工作流报错

问题描述

升级后,GitHub Actions 自动部署工作流开始报错,检查发现是 Node.js 版本过低导致的。

解决方案

修改 hexo-deploy-github-pages-action 中的 Dockerfile,将 Node.js 版本从 16 升级到 18:

1
FROM node:18

这个简单的修改就解决了工作流问题。

问题2:软件供应链问题 - Stylus 包不可用

问题描述

在升级依赖包时遇到了令人啼笑皆非的问题:

1
2
3
4
npm list
# 显示多个包版本冲突
# hexo@6.3.0 invalid: "^7.3.0" from the root project
# stylus 相关包无法正常安装

初始以为是配置问题,但经过排查发现这是一个史诗级乌龙事件

真相揭露:NPM 官方安全团队错误地将前端 CSS 预处理器 stylus 与 ChromeOS 的物理触控笔工具搞混了!

这个荒谬的误封事件源于 CVE-2025-6044,该漏洞报告的是 ChromeOS 设备上物理触控笔的安全问题,但 NPM 的自动化安全系统错误地将同名的前端 CSS 预处理器库也一并封禁。

让我们来看看这个绝世乌龙:

真正有漏洞的 “Stylus”

  • ChromeOS 设备上的物理触控笔工具
  • 需要物理接触设备才能攻击
  • 与前端开发完全无关

被误杀的 “stylus”

  • 前端开发者广泛使用的 CSS 预处理器
  • 纯软件库,连 UI 都没有
  • 被全球数百万项目依赖

这就好比因为苹果公司出了安全问题,就把超市里的苹果都下架了一样荒谬。

排查过程

  1. 检查包依赖关系
1
2
3
4
5
npm view hexo-renderer-stylus@3.0.0 dependencies
# { nib: '^1.2.0', stylus: '^0.59.0' }

npm view hexo-renderer-stylus@3.0.1 dependencies
# { nib: '^1.2.0', stylus: '^0.62.0' }
  1. 查看可用版本
1
2
npm view stylus versions
# 发现官方 npm 仓库中的 stylus 包被移除
  1. 参考解决方案
    根据 GitHub Issue 的讨论,这是一个已知问题。

临时解决方案

采用从 GitHub 直接安装的临时解决方案:

  1. 清理环境
1
2
3
4
5
# 删除 node_modules 和 lock 文件
rm -rf node_modules package-lock.json

# 清理 npm 缓存
npm cache clean --force
  1. 从 GitHub 安装 Stylus
1
npm install github:stylus/stylus#0.62.0
  1. 安装其他依赖
1
npm install
  1. 在 package.json 中使用 GitHub 源
1
2
3
4
5
{
"dependencies": {
"stylus": "github:stylus/stylus#0.62.0"
}
}

后续更新:Stylus 包已恢复

值得庆幸的是,经过社区的努力和维护者的申诉,Stylus 包已经恢复正常使用。如果你之前采用了 GitHub 直接安装的临时方案,可以按照以下步骤切换回官方版本:

步骤 1: 从 package.json 中移除 GitHub 依赖

  1. 打开你的 package.json 文件。

  2. 1
    "dependencies"

    中找到以下内容:

    1
    "stylus": "github:stylus/stylus#0.64.0"
  3. 删除这一行,修改后的部分应如下所示:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    "dependencies": {
    "hexo": "^7.3.0",
    "hexo-deployer-git": "^4.0.0",
    "hexo-generator-archive": "^2.0.0",
    "hexo-generator-category": "^2.0.0",
    "hexo-generator-feed": "^3.0.0",
    "hexo-generator-index": "^4.0.0",
    "hexo-generator-search": "^2.4.3",
    "hexo-generator-tag": "^2.0.0",
    "hexo-renderer-ejs": "^2.0.0",
    "hexo-renderer-marked": "^7.0.1",
    "hexo-renderer-pug": "^3.0.0",
    "hexo-renderer-stylus": "^3.0.1",
    "hexo-server": "^3.0.0",
    "hexo-theme-landscape": "^1.1.0",
    "hexo-wordcount": "^6.0.1"
    }

步骤 2: 删除 node_modulespackage-lock.json

为了确保所有依赖关系正确重新处理,删除现有的依赖和 package-lock.json 文件:

1
rm -rf node_modules package-lock.json

步骤 3: 重新安装依赖

在项目根目录运行以下命令,重新安装依赖:

1
npm install

注意:如果 hexo-renderer-stylus 插件依赖 stylus,它会自动安装需要的 stylus 版本,无需手动安装。这样可以确保你的项目依赖关系干净且正确。

问题3:依赖版本升级

升级过程

使用工具批量升级依赖:

1
2
3
4
5
6
7
8
# 安装升级工具
sudo npm i -g npm-check-updates

# 检查并更新 package.json
ncu -u

# 重新安装
npm install

最终依赖版本

升级前的依赖:

1
2
3
4
5
├── hexo@6.3.0
├── hexo-deployer-git@3.0.0
├── hexo-renderer-marked@6.3.0
├── hexo-renderer-stylus@3.0.0
└── ...

升级后的目标版本:

1
2
3
4
5
├── hexo@7.3.0
├── hexo-deployer-git@4.0.0
├── hexo-renderer-marked@7.0.1
├── hexo-renderer-stylus@3.0.1
└── ...

主题升级:Butterfly 更新

升级方法

  1. 下载最新版本:从 GitHub 下载 Butterfly 最新版本
  2. 覆盖主题文件夹:保留原配置文件
  3. 配置文件迁移:使用 Claude 协助合并新旧配置

配置文件更新

新版本 Butterfly 的配置结构有较大变化,主要更新包括:

  • 新的配置节点结构navcode_blockssearchsharechat
  • 新增功能配置index_layoutseriesabcjschartjsumami_analytics
  • 保留个人配置:社交链接、图片路径、侧边栏设置等
  • 更新过时配置项:名称和格式标准化

新功能配置

1. Mermaid 图表支持

由于 Butterfly 5.0.0 已内置 Mermaid 支持,移除了第三方插件:

1
npm uninstall hexo-filter-mermaid-diagrams

Hexo 配置 (_config.yml):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
highlight:
enable: true
line_number: true
auto_detect: false
tab_replace: ''
wrap: true
hljs: false
exclude_languages: ['mermaid']

prismjs:
enable: false
preprocess: true
line_number: true
tab_replace: ''
exclude_languages: ['mermaid']

Butterfly 配置

1
2
3
4
5
6
mermaid:
enable: true
code_write: true # 支持代码块方式写 Mermaid
theme:
light: default
dark: dark

现在可以直接使用代码块语法:

graph TD;
    A-->B;
    A-->C;
    B-->D;
    C-->D;

2. LaTeX 数学公式支持

配置 MathJax 支持:

1
2
3
4
5
6
7
8
9
10
11
math:
use: mathjax
per_page: false # 按需加载,在文章中设置 mathjax: true
hide_scrollbar: false

mathjax:
enableMenu: true
tags: none

katex:
copy_tex: false

使用方法

  1. 在需要数学公式的文章 Front Matter 中添加:
1
2
3
4
---
title: 示例文章
mathjax: true
---
  1. 在文章中直接使用 LaTeX 语法:

$$E = mc^2$$

$$
\int_{-\infty}^{\infty} e^{-x^2} dx = \sqrt{\pi}
$$

3. 优化图片引用

Typora中开启插入自动复制图片(本地/在线图片都可插入)。将图片自动保存到同名文件夹下./${filename}

参考:

http://edulinks.cn/2020/03/14/20200314-write-hexo-with-typora/

https://hexo.io/zh-cn/docs/asset-folders

安装插件

1
npm install hexo-image-link --save

这样,就可以直接用Typora Markdown兼容的格式加入图片。更方便本地查看和博客部署。
注意,配置中需要开启post_asset_folder: true

假设文章路径如下:

1
2
3
4
5
./source/_posts
├── demo.md
└── demo
├── a.jpg
└── cover.jpg

图片引用:

1
2
3
4
5
6
方式1: 由插件hexo-renderer-marked实现
![一张示例图片](a.jpg)


方式2: 由插件hexo-image-link实现
![一张示例图片](demo/a.jpg)
image-20250724180402723

mypic

部署测试

在推送到生产环境前,务必进行本地测试:

1
2
3
4
5
6
7
8
# 清理缓存
hexo clean

# 生成静态文件
hexo generate

# 本地预览
hexo server

确认无误后再使用 GitHub Actions 部署到公网。

经验总结

1. 供应链安全的思考

这次 Stylus 误封事件给我们带来了深刻的反思:

问题的本质

  • 过度依赖中心化平台:整个前端生态过度依赖 NPM 这个单点
  • 自动化判断的局限性:AI 和自动化工具容易出现判断错误
  • 申诉机制的缺失:维护者在遇到问题时申诉无门,只能在社交媒体求助

脆弱的现代前端生态

现代前端项目动辄数百个依赖,每个依赖都是潜在的故障点。这次事件暴露了几个关键问题:

  • 依赖树过于复杂:一个小包出问题可能导致整个项目无法构建
  • 缺乏有效的备份机制:大多数项目完全依赖官方源
  • 风险意识不足:很少有团队考虑关键依赖的备用方案

建议的改进措施

短期应对

  • 建立私有镜像:公司/团队应该建立 NPM 私有镜像
  • 锁定关键依赖:使用 package-lock.json 确保版本一致性
  • 多源备份:为关键依赖配置多个下载源

长期规划

  • 推动去中心化:支持更多元化的包管理生态
  • 改善治理机制:推动 NPM 建立更透明的决策流程
  • 支持开源维护者:给予更多资金和技术支持

2. 版本升级策略

  • 渐进式升级:避免一次性升级过多组件
  • 本地测试充分:确保功能正常后再部署
  • 配置备份:保留原始配置文件

3. 工具使用

  • npm-check-updates:批量检查依赖更新
  • GitHub 直接安装:应急解决方案
  • AI 辅助配置:利用 Claude 等工具协助配置迁移

4. 社区的力量

这次事件也让我们看到了开源社区的温暖:

  • 互助精神:开发者们积极分享解决方案
  • 维护者的责任感:@iChenLei 虽然无辜但仍为用户道歉
  • 集体智慧:社区快速找到了多种临时解决方案

结语

经过这次大更新,博客系统现在运行在更新的技术栈上,支持了 Mermaid 图表和 LaTeX 数学公式等新功能。虽然过程中经历了一场史诗级的乌龙事件,但也让我们对软件供应链安全有了更深刻的认识。

在享受开源生态便利的同时,也要时刻关注安全问题,做好应对准备。同时,开源社区的自我修复能力也是值得信赖的,大多数问题都会在社区的努力下得到及时解决。希望这篇记录能帮助遇到类似问题的朋友快速解决问题。

这次经历提醒我们:

  • 技术的脆弱性:看似强大的技术栈可能因为一个荒谬的错误而瘫痪
  • 社区的重要性:在官方渠道失效时,社区是我们最重要的支撑
  • 居安思危的必要性:平时就应该考虑备用方案,而不是等问题出现才手忙脚乱

软件正在吞噬世界,但谁来守护软件?

也许这些”灾难”正是推动我们建设更健壮、更去中心化生态系统的催化剂。希望这篇记录能帮助遇到类似问题的朋友,也希望我们的生态系统能在这些挫折中变得更加成熟和可靠。