一、前言
之前写过一篇《Windows下基于Github和Hexo搭建个人博客》的教程,当时用的环境是 Hexo 5.3.0 + NexT 8.2.1。时隔几年没有管理博客,打开一看各种依赖版本都老了,于是决定进行一次全面升级。这篇文章就记录一下升级的完整过程,顺便更新一下 GitHub Pages 的部署教程,希望对同样需要升级博客的朋友有所帮助。
本次升级涉及的主要版本变化:
| 组件 |
升级前 |
升级后 |
| Hexo |
5.3.0 |
7.3.0 |
| NexT 主题 |
8.7.0 |
8.27.0 |
| Node.js |
14.x |
24.x |
| hexo-renderer-marked |
3.x |
6.x |
| hexo-renderer-stylus |
2.x |
3.x |
| hexo-renderer-ejs |
1.x |
2.x |
| hexo-deployer-git |
GitHub dev版 |
4.0.0 |
| hexo-blog-encrypt |
3.x |
4.x |
二、为什么要升级
2.1 Hexo 5 → 7 的变化
Hexo 在 2023 年之后陆续发布了 6.x 和 7.x 版本,主要改进包括:
- 性能提升:静态页面生成速度更快
- Node.js 兼容性:支持更新的 Node.js 版本(14+)
- 依赖更新:底层依赖库全面升级,修复了安全漏洞
- 配置校验:启动时会验证配置文件,减少配置错误导致的问题
2.2 NexT 主题为什么要改成 npm 管理
之前我们是把 NexT 主题下载后放到 themes/ 文件夹下,比如 themes/next_8.7.0/。这种方式有几个缺点:
- 升级主题时需要手动下载替换整个文件夹
- 主题文件和自己的自定义配置混在一起,不好管理
- 无法通过一条命令快速更新
改为 npm 管理后,主题文件在 node_modules/ 中,自定义配置放在项目根目录的 _config.next.yml 里,升级只需 npm update hexo-theme-next。
三、升级前的准备工作
3.1 确认 Node.js 版本
Hexo 7 要求 Node.js 14 以上,推荐使用 LTS 版本。打开终端输入:
如果还没有安装 Node.js,请前往 Node.js 官网 下载安装。
3.2 备份重要文件
升级前建议备份以下文件,以防万一:
_config.yml(站点配置文件)
themes/你的主题文件夹/_config.yml(主题配置文件)
source/ 文件夹(所有文章和页面)
source/_data/(自定义模板文件,如果有的话)
四、升级 Hexo 和插件
4.1 更新 package.json
打开博客根目录下的 package.json,将依赖版本更新为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| { "name": "hexo-site", "version": "0.0.0", "private": true, "scripts": { "build": "hexo generate", "clean": "hexo clean", "deploy": "hexo deploy", "server": "hexo server" }, "hexo": { "version": "7.3.0" }, "dependencies": { "hexo": "^7.3.0", "hexo-blog-encrypt": "^4.0.0", "hexo-deployer-git": "^4.0.0", "hexo-generator-archive": "^2.0.0", "hexo-generator-category": "^2.0.0", "hexo-generator-index": "^4.0.0", "hexo-generator-tag": "^2.0.0", "hexo-renderer-ejs": "^2.0.0", "hexo-renderer-marked": "^6.0.0", "hexo-renderer-stylus": "^3.0.0", "hexo-server": "^3.0.0", "hexo-theme-next": "^8.27.0" } }
|
注意:我们把 hexo-theme-next 加到了 dependencies 里,同时移除了 hexo-theme-landscape(默认主题,不需要了)。
4.2 清理旧依赖并重新安装
1 2 3 4 5 6
| rm -rf node_modules rm package-lock.json
npm install
|
4.3 修改站点配置文件
打开根目录下的 _config.yml,将主题名从文件夹名改为 npm 包名:
1 2 3 4 5
| theme: next_8.7.0
theme: next
|
五、迁移 NexT 主题配置
这一步是升级的关键。以前主题配置写在 themes/next_8.7.0/_config.yml 里,现在要迁移到根目录的 _config.next.yml 文件中。
5.1 删除旧主题文件夹
1
| rm -rf themes/next_8.7.0
|
也可以把 themes/ 下的 hexo-theme-landscape 一起删掉,用不到了。
5.2 创建 _config.next.yml
在博客根目录下创建 _config.next.yml 文件。这里只需要写和默认值不同的配置。下面是一个完整的参考模板:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
|
scheme: Pisces
favicon: small: /images/favicon-16x16-next.png medium: /images/favicon-32x32-next.png apple_touch_icon: /images/apple-touch-icon-next.png safari_pinned_tab: /images/logo.svg
creative_commons: license: by-nc-sa size: small sidebar: false post: false language: deed.zh
menu: home: / || fa fa-home about: /about/ || fa fa-user tags: /tags/ || fa fa-tags archives: /archives/ || fa fa-archive
menu_settings: icons: true badges: false
sidebar: position: left width_expanded: 320 width_dual_column: 240 display: post padding: 18 offset: 12
avatar: url: /images/avatar.gif rounded: false rotated: false
site_state: true
social: GitHub: https://github.com/你的用户名 || fab fa-github
social_icons: enable: true icons_only: false transition: false
toc: enable: true number: true wrap: false expand_all: false max_depth: 6
footer: icon: name: fa fa-heart animated: false color: "#ff0000" powered: true
excerpt_description: true read_more_btn: true
post_meta: item_text: true created_at: true updated_at: enable: true another_day: true categories: true
tag_icon: false post_navigation: left
codeblock: theme: light: default dark: stackoverflow-dark copy_button: enable: true style: mac
back2top: enable: true sidebar: false scrollpercent: false
motion: enable: true transition: menu_item: fadeInDown post_block: fadeIn post_header: fadeInDown post_body: fadeInDown coll_header: fadeInLeft sidebar: fadeInUp
custom_file_path: footer: source/_data/footer.njk
vendors: internal: local plugins: cdnjs
|
把上面的 你的用户名 和 你的邮箱 替换成你自己的信息,其他配置按需修改即可。
5.3 测试构建
1 2
| hexo clean hexo generate
|
如果没有报错,说明升级成功。可以运行 hexo server 在本地 http://localhost:4000 预览效果。
六、配置 SSH 密钥连接 GitHub
部署到 GitHub Pages 需要通过 SSH 密钥认证。如果你之前配置过但密钥丢失了,需要重新生成。
6.1 生成 SSH 密钥
打开 Git Bash,输入:
1
| ssh-keygen -t ed25519 -C "你的GitHub用户名"
|
一路回车即可(默认不需要设置密码)。生成的密钥文件在 ~/.ssh/ 目录下:
id_ed25519:私钥(不要泄露!)
id_ed25519.pub:公钥(需要添加到 GitHub)
6.2 将公钥添加到 GitHub
- 复制公钥内容:
1
| cat ~/.ssh/id_ed25519.pub
|
- 打开 GitHub SSH Keys 设置页面
- 点击 New SSH key
- Title 随便填,比如
我的电脑
- Key 里粘贴刚才复制的公钥内容
- 点击 Add SSH key
6.3 测试连接
如果看到类似以下内容,说明配置成功:
1
| Hi 你的用户名! You've successfully authenticated, but GitHub does not provide shell access.
|
七、部署到 GitHub Pages
7.1 确认仓库设置
- 打开你的 GitHub 仓库(
username.github.io)
- 进入 Settings → Pages
- Source 选择 Deploy from a branch
- Branch 选择 main,文件夹选 / (root)
- 点击 Save
7.2 配置部署信息
确认 _config.yml 最后的 deploy 配置:
1 2 3 4
| deploy: type: git repository: git@github.com:你的用户名/你的用户名.github.io.git branch: main
|
7.3 创建部署脚本
由于不同电脑上 Git 和 Node.js 的安装路径不同,hexo deploy 有时会找不到 git 命令。这里提供一个通用的部署脚本 deploy.js,放在博客根目录下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
| const fs = require('fs'); const path = require('path'); const { execSync } = require('child_process');
const GIT = 'Git安装路径\\cmd\\git.exe';
const publicDir = path.join(__dirname, 'public'); const deployDir = path.join(__dirname, '.deploy_git');
const config = require('js-yaml').load( fs.readFileSync(path.join(__dirname, '_config.yml'), 'utf8') ); const repo = config.deploy.repository; const branch = config.deploy.branch || 'main';
function run(cmd, opts = {}) { console.log('>', cmd); return execSync(cmd, { encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'], env: { ...process.env, GIT_SSH_COMMAND: 'ssh -o StrictHostKeyChecking=no' }, ...opts }); }
function copyDirSync(src, dest) { if (!fs.existsSync(dest)) fs.mkdirSync(dest, { recursive: true }); for (const entry of fs.readdirSync(src, { withFileTypes: true })) { const srcPath = path.join(src, entry.name); const destPath = path.join(dest, entry.name); if (entry.isDirectory()) { copyDirSync(srcPath, destPath); } else { fs.copyFileSync(srcPath, destPath); } } }
try { console.log('\n=== 生成静态文件 ==='); const hexoBin = path.join(__dirname, 'node_modules', 'hexo', 'bin', 'hexo'); run(`node "${hexoBin}" generate`, { cwd: __dirname });
console.log('\n=== 准备部署目录 ==='); if (!fs.existsSync(deployDir)) { fs.mkdirSync(deployDir, { recursive: true }); } run(`"${GIT}" init`, { cwd: deployDir }); run(`"${GIT}" config user.email "deploy@users.noreply.github.com"`, { cwd: deployDir }); run(`"${GIT}" config user.name "deploy"`, { cwd: deployDir }); try { run(`"${GIT}" checkout ${branch}`, { cwd: deployDir }); } catch (e) { run(`"${GIT}" checkout -b ${branch}`, { cwd: deployDir }); }
console.log('\n=== 复制文件 ==='); for (const entry of fs.readdirSync(deployDir)) { if (entry === '.git') continue; fs.rmSync(path.join(deployDir, entry), { recursive: true, force: true }); } copyDirSync(publicDir, deployDir);
console.log('\n=== 提交并推送 ==='); run(`"${GIT}" add -A`, { cwd: deployDir }); try { run(`"${GIT}" diff --cached --quiet`, { cwd: deployDir }); console.log('没有变更,无需部署。'); } catch (e) { const now = new Date().toISOString(); run(`"${GIT}" commit -m "Site updated: ${now}"`, { cwd: deployDir }); run(`"${GIT}" push --force "${repo}" ${branch}`, { cwd: deployDir }); console.log('\n部署成功!'); } } catch (err) { console.error('\n部署失败:', err.message); process.exit(1); }
|
使用前需要修改脚本中的 GIT 变量,改成你电脑上 git.exe 的实际路径。
如何找到 git.exe 的路径?
在终端输入 where git(Windows cmd)或 which git(Git Bash),找到路径后把 git.exe 的完整路径填进去。
7.4 一键部署
脚本会自动执行:生成静态文件 → 复制到部署目录 → Git 提交 → 推送到 GitHub。
推送成功后,稍等一两分钟,打开 https://你的用户名.github.io 就能看到更新后的博客了。
八、日常操作速查
| 操作 |
命令 |
| 新建文章 |
hexo new "文章标题" |
| 本地预览 |
hexo server,访问 localhost:4000 |
| 生成静态文件 |
hexo clean && hexo generate |
| 部署到 GitHub |
node deploy.js |
| 升级 NexT 主题 |
npm update hexo-theme-next |
| 升级所有插件 |
npm update |
九、踩坑记录
9.1 hexo-blog-encrypt v4 的变化
如果你的文章使用了加密功能(hexo-blog-encrypt),v4 版本废弃了 wrong_hash_message 字段,统一使用 wrong_pass_message。升级后如果有警告提示,把文章 front-matter 中的 wrong_hash_message 改成 wrong_pass_message 即可。
9.2 新浪图床可能失效
早期文章中的图片如果使用了 sinaimg.cn 的外链,可能已经无法访问。建议把图片迁移到本地 source/images/ 目录下,或者使用其他图床服务。
9.3 Git 找不到的问题
如果 hexo deploy 提示 spawn git ENOENT,说明 Git 没有加入系统 PATH 环境变量。可以:
- 把 Git 的安装路径(如
C:\Program Files\Git\cmd)添加到系统环境变量 PATH 中
- 或者使用上面的
deploy.js 脚本,在脚本中指定 Git 路径
十、总结
这次升级主要做了三件事:
- Hexo 从 5.x 升级到 7.x,享受更快的构建速度和更好的兼容性
- NexT 主题改为 npm 管理,以后升级只需一条命令
- 配置 SSH 密钥和部署脚本,实现一键部署到 GitHub Pages
升级过程并不复杂,核心就是更新 package.json、修改站点配置中的主题名、创建 _config.next.yml、重新安装依赖。如果你也很久没管理自己的 Hexo 协客了,不妨花半小时升级一下,体验会好很多。