Hexo 与 Next 版本升级教程

前言

Next 各版本的仓库

年份版本仓库
2014 ~ 2017v5https://github.com/iissnan/hexo-theme-next
2018 ~ 2019v6 ~ v7https://github.com/theme-next/hexo-theme-next
2020v8https://github.com/next-theme/hexo-theme-next

Next 与 Hexo 版本适配关系

next-hexo-version

NodeJS 版本升级

NodeJS 版本升级不是必须的,可以根据自己的实际情况选择是否升级,首先在 NodeJS 官网下载最新版的二进制安装包,解压后配置系统环境变量即可。

1
2
3
4
5
6
7
8
9
# 配置环境变量
# vim /etc/profile
export PATH=$PATH:/usr/local/node-v14.16.1/bin
NODE_PATH=/usr/local/node-v14.16.1/lib/node_modules
PATH=$PATH:$NODE_PATH
export NODE_PATH PATH

# 使配置生效
# source /etc/profile

Hexo 版本升级

笔者是从 Hexo 3.9.0 升级到 Hexo 5.4.0,步骤如下:

全局升级 Hexo 版本

若曾经在系统里,直接使用过 hexo 的命令,才需要执行以下升级操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 清理NPM缓存
$ npm cache clean -f

# 全局安装版本检测、版本升级工具
$ npm install -g npm-check
$ npm install -g npm-upgrade

# 全局检测哪些模块可以升级,这里可以根据打印的提示信息,手动安装最新版本的模块
$ npm-check -g

# 全局更新模块
$ npm update -g

# 全局安装或更新Hexo的最新版本
$ npm install --global hexo

博客升级 Hexo 版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 进入博客的根目录
$ cd /blog-root

# 检测Hexo哪些模块可以升级
$ npm-check

# 删除package-lock.json
# rm -rf package-lock.json

# 更新package.json
$ npm-upgrade

# 删除整个模块目录,这样可以避免很多坑
$ rm -rf node_modules

# 更新Hexo的模块
$ npm update --save

# 若出现依赖的问题,用以下命令检查一下,然后把报错的统一修复一下即可
$ npm audix

# 或者强制更新
$ npm update --save --force

由于新版的 Hexo 一般增加了不少新特性,因此需要使用新版 Hexo 默认的配置模版文件 _config.yml,同时还需要稍微更改旧版的 package.json 配置文件,否则容易出现各种兼容错误

1
2
3
4
5
6
# 进入博客的根目录
$ cd /blog-root

# 备份旧版的配置文件
$ mv _config.yml _config.yml.bak
$ mv package.json package.json.bak
1
2
3
4
5
6
7
8
$ 单独初始化全新的Hexo博客目录
$ hexo init hexo-upgrade

$ 拷贝新的配置模版文件到博客的根目录
$ cp hexo-upgrade/_config.yml /blog-root/_config.yml
$ cp hexo-upgrade/package.json /blog-root/package.json

# 最后在新的配置模版文件里,重新追加旧版的Hexo配置内容

升级 Next 主题

注意事项

笔者 从 Next 7.8.0 升级到 Next 8.3.0,值得一提的是,Next 版本升级必须注意以下事项:

  • Next 与 Hexo 的版本必须兼容
  • 必须使用新版 Next 主题的 _config.yml 配置文件,若继续使用 Next 旧版的 _config.yml 配置文件,容易出现各种兼容错误

版本升级

1
2
3
4
5
6
7
8
9
10
# 进入博客的主题目录
$ cd /boot-root/theme

# 备份旧版主题的配置
$ mv next next-bak

# 拉取最新的代码(注意:Next不同版本使用不同的仓库)
$ git clone https://github.com/next-theme/hexo-theme-next next

# 最后将旧版的Next配置内容追加到Next新版的配置文件中,包括拷贝旧版自定义的样式、布局文件等

本地下载第三方库(可选)

在 Next 8.3.0 的 _config.yml 中,新增了 vendors.internal 属性(如下配置)来指定加载本地的第三方库文件,默认存放路径为 themes/next/source/lib;启用后站点就不再需要依赖第三方的 CDN 资源,而是直接使用本地站点的资源文件,这样可以让站点的访问速度更稳定。

1
2
3
4
5
6
7
8
9
10
11
# It's recommended to use the same version as in `_vendors.yml` to avoid potential problems.
# Remember to use the HTTPS protocol of CDN links when you enable HTTPS on your site.
vendors:
# The CDN provider of NexT internal scripts.
# Available values: local | jsdelivr | unpkg | cdnjs
# Warning: If you are using the latest master branch of NexT, please set `internal: local`
internal: local
# The default CDN provider of third-party plugins.
# Available values: local | jsdelivr | unpkg | cdnjs
# Dependencies for `plugins: local`: https://github.com/next-theme/plugins
plugins: local

安装 NexT 插件

特别注意

若希望使用本地的第三方库文件,则需要安装 NexT 的 @next-theme/plugins 插件,其中插件的版本必须与 NexT 主题的版本一致。

1
2
# 安装插件
$ npm install @next-theme/plugins --save

批量下载第三方库

themes/next/_vendors.yml 里定义的第三方库文件统一下载下来,并存放在 themes/next/source/lib 目录下,具体步骤如下

  • 临时更改 themes/next/scripts/events/lib/vendors.js 源文件的代码(如下所示),然后执行 hexo g 命令,从输出日志信息中得到批量下载第三方库文件的 curl 命令
  • 将得到的所有 curl 命令保存到 Shell 脚本文件里,然后执行 Shell 脚本文件批量下载第三方库文件到 themes/next/source/lib 目录下
  • 最后还原 themes/next/scripts/events/lib/vendors.js 源文件的代码
1
2
3
4
5
6
7
8
9
10
11
// 打印下载命令
const { name, version, file, alias, unavailable } = value;
if (version) {
var _path = `https://cdn.jsdelivr.net/npm/${name}@${version}/${file}`;
console.log("curl " + _path + " --create-dirs -o ${DIR}" + "/" + name + "/" + file);
continue;
}

const links = {
// 省略 ...
};

批量下载 Next 8.3.0 版本所需的第三方库文件的 Shell 脚本文件如下,DIRthemes/next/source/lib 目录的绝对路径,请自行更改

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
#!/bin/sh

DIR=/usr/local/hexo-develop/themes/next/source/lib
rm -rf ${DIR}/*

curl https://cdn.jsdelivr.net/npm/animejs@3.2.1/lib/anime.min.js --create-dirs -o ${DIR}/animejs/lib/anime.min.js
curl https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5.15.3/css/all.min.css --create-dirs -o ${DIR}/@fortawesome/fontawesome-free/css/all.min.css
curl https://cdn.jsdelivr.net/npm/prismjs@1.23.0/components/prism-core.min.js --create-dirs -o ${DIR}/prismjs/components/prism-core.min.js
curl https://cdn.jsdelivr.net/npm/prismjs@1.23.0/plugins/autoloader/prism-autoloader.min.js --create-dirs -o ${DIR}/prismjs/plugins/autoloader/prism-autoloader.min.js
curl https://cdn.jsdelivr.net/npm/prismjs@1.23.0/plugins/line-numbers/prism-line-numbers.min.js --create-dirs -o ${DIR}/prismjs/plugins/line-numbers/prism-line-numbers.min.js
curl https://cdn.jsdelivr.net/npm/mathjax@3.1.2/es5/tex-mml-chtml.js --create-dirs -o ${DIR}/mathjax/es5/tex-mml-chtml.js
curl https://cdn.jsdelivr.net/npm/katex@0.13.0/dist/katex.min.css --create-dirs -o ${DIR}/katex/dist/katex.min.css
curl https://cdn.jsdelivr.net/npm/katex@0.13.0/dist/contrib/copy-tex.min.js --create-dirs -o ${DIR}/katex/dist/contrib/copy-tex.min.js
curl https://cdn.jsdelivr.net/npm/katex@0.13.0/dist/contrib/copy-tex.min.css --create-dirs -o ${DIR}/katex/dist/contrib/copy-tex.min.css
curl https://cdn.jsdelivr.net/npm/@next-theme/pjax@0.4.0/pjax.min.js --create-dirs -o ${DIR}/@next-theme/pjax/pjax.min.js
curl https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js --create-dirs -o ${DIR}/jquery/dist/jquery.min.js
curl https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.js --create-dirs -o ${DIR}/@fancyapps/fancybox/dist/jquery.fancybox.min.js
curl https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.css --create-dirs -o ${DIR}/@fancyapps/fancybox/dist/jquery.fancybox.min.css
curl https://cdn.jsdelivr.net/npm/medium-zoom@1.0.6/dist/medium-zoom.min.js --create-dirs -o ${DIR}/medium-zoom/dist/medium-zoom.min.js
curl https://cdn.jsdelivr.net/npm/lozad@1.16.0/dist/lozad.min.js --create-dirs -o ${DIR}/lozad/dist/lozad.min.js
curl https://cdn.jsdelivr.net/npm/pangu@4.0.7/dist/browser/pangu.min.js --create-dirs -o ${DIR}/pangu/dist/browser/pangu.min.js
curl https://cdn.jsdelivr.net/npm/quicklink@2.1.0/dist/quicklink.umd.js --create-dirs -o ${DIR}/quicklink/dist/quicklink.umd.js
curl https://cdn.jsdelivr.net/npm/disqusjs@1.3.0/dist/disqus.js --create-dirs -o ${DIR}/disqusjs/dist/disqus.js
curl https://cdn.jsdelivr.net/npm/disqusjs@1.3.0/dist/disqusjs.css --create-dirs -o ${DIR}/disqusjs/dist/disqusjs.css
curl https://cdn.jsdelivr.net/npm/gitalk@1.7.2/dist/gitalk.min.js --create-dirs -o ${DIR}/gitalk/dist/gitalk.min.js
curl https://cdn.jsdelivr.net/npm/gitalk@1.7.2/dist/gitalk.css --create-dirs -o ${DIR}/gitalk/dist/gitalk.css
curl https://cdn.jsdelivr.net/npm/firebase@8.3.1/firebase-app.js --create-dirs -o ${DIR}/firebase/firebase-app.js
curl https://cdn.jsdelivr.net/npm/firebase@8.3.1/firebase-firestore.js --create-dirs -o ${DIR}/firebase/firebase-firestore.js
curl https://cdn.jsdelivr.net/npm/algoliasearch@4.8.6/dist/algoliasearch-lite.umd.js --create-dirs -o ${DIR}/algoliasearch/dist/algoliasearch-lite.umd.js
curl https://cdn.jsdelivr.net/npm/instantsearch.js@4.19.0/dist/instantsearch.production.min.js --create-dirs -o ${DIR}/instantsearch.js/dist/instantsearch.production.min.js
curl https://cdn.jsdelivr.net/npm/pdfobject@2.2.5/pdfobject.min.js --create-dirs -o ${DIR}/pdfobject/pdfobject.min.js
curl https://cdn.jsdelivr.net/npm/mermaid@8.9.2/dist/mermaid.min.js --create-dirs -o ${DIR}/mermaid/dist/mermaid.min.js
curl https://cdn.jsdelivr.net/npm/animate.css@3.1.1/animate.min.css --create-dirs -o ${DIR}/animate.css/animate.min.css
curl https://cdn.jsdelivr.net/npm/nprogress@0.2.0/nprogress.js --create-dirs -o ${DIR}/nprogress/nprogress.js
curl https://cdn.jsdelivr.net/npm/nprogress@0.2.0/nprogress.css --create-dirs -o ${DIR}/nprogress/nprogress.css
curl https://cdn.jsdelivr.net/npm/ribbon.js@1.0.2/dist/ribbon.min.js --create-dirs -o ${DIR}/ribbon.js/dist/ribbon.min.js

常见问题

问题一

完成上述升级操作后,执行 hexo generator 命令后,themes/next/scripts/events/lib/vendors.js 的代码里面抛出以下错误信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
INFO  Start processing
FATAL {
err: TypeError: Cannot read property 'call' of undefined
at module.exports (/usr/local/hexo-develop/themes/next/scripts/events/lib/vendors.js:27:25)
at Hexo.<anonymous> (/usr/local/hexo-develop/themes/next/scripts/events/index.js:9:27)
at Hexo.tryCatcher (/usr/local/hexo-develop/node_modules/bluebird/js/release/util.js:16:23)
at Hexo.<anonymous> (/usr/local/hexo-develop/node_modules/bluebird/js/release/method.js:15:34)
at /usr/local/hexo-develop/node_modules/hexo/lib/extend/filter.js:67:52
at tryCatcher (/usr/local/hexo-develop/node_modules/bluebird/js/release/util.js:16:23)
at Object.gotValue (/usr/local/hexo-develop/node_modules/bluebird/js/release/reduce.js:166:18)
at Object.gotAccum (/usr/local/hexo-develop/node_modules/bluebird/js/release/reduce.js:155:25)
at Object.tryCatcher (/usr/local/hexo-develop/node_modules/bluebird/js/release/util.js:16:23)
at Promise._settlePromiseFromHandler (/usr/local/hexo-develop/node_modules/bluebird/js/release/promise.js:547:31)
at Promise._settlePromise (/usr/local/hexo-develop/node_modules/bluebird/js/release/promise.js:604:18)
at Promise._settlePromiseCtx (/usr/local/hexo-develop/node_modules/bluebird/js/release/promise.js:641:10)
at _drainQueueStep (/usr/local/hexo-develop/node_modules/bluebird/js/release/async.js:97:12)
at _drainQueue (/usr/local/hexo-develop/node_modules/bluebird/js/release/async.js:86:9)
at Async._drainQueues (/usr/local/hexo-develop/node_modules/bluebird/js/release/async.js:102:5)
at Immediate.Async.drainQueues [as _onImmediate] (/usr/local/hexo-develop/node_modules/bluebird/js/release/async.js:15:14)
at processImmediate (internal/timers.js:461:21)

这一般是 Hexo 的部分模块没有成功更新引起,例如 hexo-util 模块更新失败,最终导致代码不兼容。首先检查 hexo-util 模块的版本,然后可以尝试执行以下命令,强制更新 hexo-util 模块

1
2
3
4
5
# 进入博客的主题目录
$ cd /boot-root/

# 强制更新
$ npm update --save --force

问题二

完成上述升级操作后,执行 hexo generator 命令后,Hexo 会抛出以下错误信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
FATAL { err:
TypeError: line.matchAll is not a function
at res.value.res.value.split.map.line (/usr/local/hexo-develop/node_modules/hexo-util/lib/highlight.js:128:26)
at Array.map (<anonymous>)
at closeTags (/usr/local/hexo-develop/node_modules/hexo-util/lib/highlight.js:126:37)
at highlight (/usr/local/hexo-develop/node_modules/hexo-util/lib/highlight.js:119:10)
at highlightUtil (/usr/local/hexo-develop/node_modules/hexo-util/lib/highlight.js:23:16)
at data.content.dataContent.replace (/usr/local/hexo-develop/node_modules/hexo/lib/plugins/filter/before_post_render/backtick_code_block.js:92:17)
at String.replace (<anonymous>)
at Hexo.backtickCodeBlock (/usr/local/hexo-develop/node_modules/hexo/lib/plugins/filter/before_post_render/backtick_code_block.js:19:30)
at Hexo.tryCatcher (/usr/local/hexo-develop/node_modules/bluebird/js/release/util.js:16:23)
at Hexo.<anonymous> (/usr/local/hexo-develop/node_modules/bluebird/js/release/method.js:15:34)
at Promise.each.filter (/usr/local/hexo-develop/node_modules/hexo/lib/extend/filter.js:67:52)
at tryCatcher (/usr/local/hexo-develop/node_modules/bluebird/js/release/util.js:16:23)
at Object.gotValue (/usr/local/hexo-develop/node_modules/bluebird/js/release/reduce.js:166:18)
at Object.gotAccum (/usr/local/hexo-develop/node_modules/bluebird/js/release/reduce.js:155:25)
at Object.tryCatcher (/usr/local/hexo-develop/node_modules/bluebird/js/release/util.js:16:23)
at Promise._settlePromiseFromHandler (/usr/local/hexo-develop/node_modules/bluebird/js/release/promise.js:547:31)
at Promise._settlePromise (/usr/local/hexo-develop/node_modules/bluebird/js/release/promise.js:604:18)
at Promise._settlePromise0 (/usr/local/hexo-develop/node_modules/bluebird/js/release/promise.js:649:10)
at Promise._settlePromises (/usr/local/hexo-develop/node_modules/bluebird/js/release/promise.js:729:18)
at _drainQueueStep (/usr/local/hexo-develop/node_modules/bluebird/js/release/async.js:93:12)
at _drainQueue (/usr/local/hexo-develop/node_modules/bluebird/js/release/async.js:86:9)

NodeJS 从 12.0.0 才开始支持函数 String.matchAll(),如果 NodeJS 的版本低于 12.0.0,那么执行 Hexo 的构建命令就会出现上述的错误,解决方法如下:

  • 方法一:将 NodeJs 升级到高于 12.0.0 的版本
  • 方法二:更改 Hexo 的配置文件 _config.yml,禁用 highlight 的功能,这样就可以避免出错,但这将会关闭代码的高亮显示功能
1
2
highlight:
enable: false