Hexo框架与NexT主题升级笔记

前言

静态博客这种东西,建站一时爽,升级火葬场。后者在前人向技术小白安利静态博客时通常不会说。不仅各种环境、框架、主题、插件模块需要一一更新,每次更新还需要对已有的定制化功能逐一手动合并。各种模块由于由不同的作者维护,更新频率不同(有些甚至已经不再更新),由此产生的各种报错和冲突也让人抓狂。

或许有不少人在搭建起静态博客后就一个版本用到死,这肯定没什么问题,但是新版本的升级会带来性能的优化和功能的更新,不享受一下就太可惜了。例如Hexo框架,从3.9升级到5.0后,不仅静态网页的渲染速度加快,还有一个非常实用的功能就是针对主题的安装和更新出了新的功能性变动,从此升级主题就变得安全无痛了。

我拿着建站时的 Hexo 3.9 + NexT 6.5 用了好几年,去年11月时终于咬咬牙做了一次大的版本升级,这之后Hexo又经历了一次大版本更新,NexT主题也更新了两个版本。虽然还是有一些技术性的问题没有搞懂(这也是为什么迟迟没有写一篇博文),不过还是记录一下,留待参考。一言以蔽之,我还是推荐静态博客的博主跟随一下版本更新,紧跟版本更新比起跨版本的大动作是轻松多了,而且得益于Hexo的新功能,主题更新也变成了一件愉快的事。

升级Node.js

Node.js是Hexo所使用的环境,不是必须要升级到最新版,但是必须满足Hexo对Node.js的版本要求。当前Hexo最新版的要求:

Node.js的升级步骤跟安装一样,上Node.js官网下载安装文件,一路点击下一步安装覆盖即可。安装完毕后可查看一下版本:

1
2
node -v # 显示node.js版本
npm -v # 显示npm版本

对于国内用户来说,可设置淘宝镜像源,下载会比较稳定:

1
npm install -g cnpm --registry=https://registry.npm.taobao.org

cnpm支持npm除了publish之外的所有命令,之后使用cnpm即可。

升级Hexo

Hexo官方文档写得实在是太简略了,连如何升级都不讲,可能默认会使用框架的都是有一定技术能力的人,但其实也未必尽然。Hexo的升级方法我参考了博主Clay的《Hexo 与 Next 版本升级教程》这篇博文(感谢大佬),步骤很清晰,习惯也非常好。不过我个人不建议直接删除整个node_modules文件夹,有点暴力,如果真想这么做的话,至少要先把原来的node_modules文件夹备份一下,出问题还可以恢复回去。就我个人而言,直接升级模块没遇到什么大的问题,反而是重新安装node_modules后各种报错。

由于上述博文也采用BY-NC-SA许可协议,冒昧将相关内容引用如下(有少许修改):

全局升级 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

# 备份模块目录(视情况操作)
# mv node_modules/ node_modules.bak/

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

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 进入博客的根目录
$ cd /blog-root

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

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

# 最后在新的配置模版文件里,重新追加旧版的Hexo配置内容(可使用Beyond Compare等文本对比工具)

升级NexT主题及进行自定义配置

如前所述,Hexo 5.0针对主题的安装和更新开发了一个非常好用的功能,详情可阅读博主Sukka所撰写的博文《Hexo 5.0.0 正式发布》。有了这个新功能后,可直接用npm安装和更新Hexo主题,主题将会安装到node_modules文件夹中,不再像以前一样需要将文件放到themes文件夹里。因此themes文件夹中的主题文件就可以删除了,不过请务必保留原先主题的相关自定义配置(详见下文),以便对照更新到新的主题中。

升级NexT主题

首先需要说明一下NexT主题的版本问题。由于NexT主题由民间爱好者团队开发和维护,中间难免会有核心成员弃坑的行为,所以迄今为止已经换了3个团队,当前是在next-theme/hexo-theme-next这个仓库进行更新,大概一个月发布一个新版本:

年份 版本 GitHub仓库
2014 ~ 2017 v5 https://github.com/iissnan/hexo-theme-next
2018 ~ 2019 v6 ~ v7 https://github.com/theme-next/hexo-theme-next
2020 ~ v8 https://github.com/next-theme/hexo-theme-next

同时,当前这个团队还设立了官方博客,并写了很详细的文档(Hexo团队你们看看人家),非常值得参详。

首先,在任何一次版本升级之前,先查看Releases或者官方博客上的更新说明,特别注意其中的Breaking Changes是否有需要我们额外注意的地方。

常规的版本升级,只需要:

1
2
3
4
# 进入博客的根目录
$ cd hexo-site
# 安装最新版本的NexT主题
$ npm install hexo-theme-next@latest

如果是跨版本升级,就需要仔细阅读官方文档中Upgrade from Legacy Version的相关条目。就当前所列出的事项简述如下:

重大变化

  1. 更新语言配置(针对简体中文)
    从v6.0.3起,zh-Hans改名为zh-CN:v6.0.3更新说明
    升级到v6.0.3及之后版本的用户需要在Hexo的_config.yml文件中修改为:language: zh-CN,否则语言显示会不正确。
  2. 从v8.0.0开始,next/source/lib文件夹下的所有插件转移至@next-theme/plugins。关于新的第三方插件的安装方法请看:Adding Plugins

升级

建议采用以下步骤从v5或v7升级到v8:

  1. 备份一些旧版本的NexT文件:
    1.1. _config.ymlnext.yml(如使用Alternate Theme Config)。
    1.2. next/source/css/_custom/*next/source/css/_variables/*中的自定义CSS文件。
    1.3. next/layout/_custom/*中的自定义布局文件。
    1.4. 任何其他可能的自定义文件,可通过比对工具比较仓库找到。
  2. 重命名旧版本的NexT文件夹,如将next重命名为next-old
  3. 按照上文提供的常规版本升级的方法安装新版本。运行hexo cleanhexo s以检查网站是否正常工作。
  4. 更新Hexo和Hexo插件
    若完成上述步骤后,执行hexo shexo g时出现错误,则旧版本的Hexo/Hexo插件与新版本的主题NexT之间可能存在冲突。建议将Hexo升级到5.0或更高版本,并将Hexo插件升级到最新版本。可运行npm outdated来查看所有可升级的插件。
    如有任何错误或不喜欢当前版本,可随时切换回旧版本。

NexT自定义主题配置

自定义config文件

升级到Hexo 5.0之后,更改主题的_config.yml(注意并非站点的_config.yml)不再需要在文件中修改,而是可以在站点的根目录(注意并非主题的根目录)下新建_config.[name].yml文件,其中[name]为主题名称(针对NexT主题,文件名为_config.next.yml),并在_config.next.yml文件中单独列出所需要的修改。

例如,我需要自定义NexT主题的_config.yml中CC协议的相关设置。默认设置为:

1
2
3
4
5
6
7
8
9
10
creative_commons:
# Available values: by | by-nc | by-nc-nd | by-nc-sa | by-nd | by-sa | cc-zero
license: by-nc-sa
# Available values: big | small
size: small
sidebar: false
post: false
# You can set a language value if you prefer a translated version of CC license, e.g. deed.zh
# CC licenses are available in 39 languages, you can find the specific and correct abbreviation you need on https://creativecommons.org
language:

我想在sidebar和post中都添加CC协议,那么可以在_config.next.yml中添加:

1
2
3
creative_commons:
sidebar: true
post: true

之后,无论怎么更新NexT主题,我在_config.next.yml中添加的设置都会对应地进行覆盖,而不影响其他的设置。(git要是有办法能这么merge就好了。)

更多阅读:官方文档Configuration页。

外观设置

在新版本的NexT主题中,对外观、布局的自定义设置可以通过在站点/source/_data文件夹中新建相应的stylus文件,并添加至_config.next.yml实现:

1
2
3
4
5
6
7
8
9
10
11
custom_file_path:
#head: source/_data/head.njk
#header: source/_data/header.njk
#sidebar: source/_data/sidebar.njk
#postMeta: source/_data/post-meta.njk
#postBodyEnd: source/_data/post-body-end.njk
#footer: source/_data/footer.njk
#bodyEnd: source/_data/body-end.njk
#variable: source/_data/variables.styl
#mixin: source/_data/mixins.styl
#style: source/_data/styles.styl

例如,新版本的NexT主题所有字号都变大了(Misc),我希望缩小字号,那么就可以在站点/source/_data文件夹中新建variables.styl文件,并在文件中添加:

1
2
3
4
5
// Font size of articles.
$font-size-base = 14px

// Font size of table and code.
$table-font-size = 14px

然后,在_config.next.yml文件中添加:

1
2
custom_file_path:
variable: source/_data/variables.styl

重新生成静态网页,就可以看到效果了。同样,无论怎么更新NexT主题,相应的效果都会进行精准覆盖,而不影响其他效果。

更多阅读:官方文档Custom Files页、Miscellaneous页,等。我所举的例子只是九牛一毛,作为Hexo最受欢迎的主题,NexT提供的(不用博主自己手写代码的)自定义空间是相当大的。

若干问题

生成静态网页时出现“Accessing non-existent property [something] of module exports inside circular dependency”报错

具体错误提示如下:

1
2
3
4
5
6
7
(node:17236) Warning: Accessing non-existent property 'lineno' of module exports inside circular dependency
(Use `node --trace-warnings ...` to show where the warning was created)
(node:17236) Warning: Accessing non-existent property 'column' of module exports inside circular dependency
(node:17236) Warning: Accessing non-existent property 'filename' of module exports inside circular dependency
(node:17236) Warning: Accessing non-existent property 'lineno' of module exports inside circular dependency
(node:17236) Warning: Accessing non-existent property 'column' of module exports inside circular dependency
(node:17236) Warning: Accessing non-existent property 'filename' of module exports inside circular dependency

疑与升级Node.js至14.0有关,似乎无实质影响。详细问题及解决方法可参考《解决 Hexo 在使用 Node.js 14 时的 Accessing non-existent property ‘xxx’ of module exports inside circular dependency 问题》一文。