搭建个人博客(下)
前言
上一篇博客主要分享了我一路把 Hexo 博客搭到能用的流程,看着就像一篇正经介绍的教程。这其实是因为截至上篇结尾我都是顺风顺水地跟着大佬们的文章走的。但这回就得好好介绍介绍我被 clover 狠狠拷打的故事了
主题
不介意的话 Hexo 默认的 landscape 也不是不行,但我在翻阅一篇掘金的主题推荐时被 clover 狠狠地吸引了
好,既然选定了主题,那就赶紧整起来!
跟着 clover 主题的 README.md 一步步走:
git clone https://github.com/esappear/hexo-theme-clover themes/clover
npm install hexo-renderer-sass --save
改一下根目录的 _config.yml:
theme: clover
highlight:
enable: false
把几个主界面的文件创建好:
hexo new page "tags"
---
layout: tag
title: tags
---
hexo new page "categories"
---
layout: category
title: categories
---
hexo new page "about"
---
layout: about
title: about
---
Generate!
ERROR ReferenceError: _ is not defined
啊?
bug
我看着报错信息,大脑宕机了一瞬间。不过既然出问题了,那就去 GitHub 上翻翻 issue。一看,最新的 issue 提到的就是这个问题:

好家伙,都是三年前的 issue 了,看看解决了没:

行吧,看来只能自己动手丰衣足食了
修bug
叠个甲,我此前几乎完全没有 Javascript 基础,所有相关知识都是现学现卖,解决方法可能又莽又蠢,大佬们轻点喷😫
一把梭
再看一眼报错信息:
ERROR ReferenceError: _ is not defined
这个报错在 layout 文件夹下的 archive.ejs、category.ejs、tag.ejs,以及 layout/_partial 里的 footer.ejs、nav.ejs 都有发生。看起来是一个变量未定义的问题,先去找找这个下划线是何方神圣。一路找到 scripts/home.js 里:
'use strict';
var pagination = require('hexo-pagination');
var assign = require('object-assign');
var _ = require('lodash');
看起来这个下划线本来应该是一个叫 lodash 的导入的库,但不知道为什么这些 ejs 模板没办法使用这个变量,我本着最简单直接的想法(未定义就再给它定义上)在所有报错的文件开头都加了一句:
var _ = require('lodash');
再跑一遍试试:
ERROR ReferenceError: require is not defined
看来是我想得太简单了
一点 Javascript 历史
话说 require 是 Javascript 中的导入函数,直觉上这类函数应该是语言本身的内置函数,怎么会未定义呢?我去网上翻了翻,发现这似乎与 Javascript 作为浏览器脚本语言的定位有关
根据这篇博客园的文章,Javascript 并不是一种模块化编程语言,在 es6 之前它是不支持类(class)的,自然也没有模块一说。2009年,美国程序员 Ryan Dahl 创立了 Nodejs 项目,将 Javascript 语言用于服务器端编程。前端的复杂程度有限,没有模块也是可以的,但是在服务器端,一定要有模块,与操作系统和其他应用程序互动,否则根本没法编程。Nodejs 使用了 CommonJS 规范来实现模块化编程,require 就是其中加载模块的全局性方法
但 Hexo 不就是基于 Nodejs 环境的吗,怎么会用不了 require 呢?
我又找到了一篇文章,似乎是因为在 Nodejs 大版本 14 以上,require 作为 CommonJS 的一个命令已经不支持直接使用了。文章也给出了解决方法:
import { createRequire } from 'module';
const require = createRequire(import.meta.url);
试试:
ERROR SyntaxError: Cannot use import statement outside a module while compiling ejs
这回网上的解决方法有两种:
- 使用
.mjs后缀名。 - 在
package.json中加入"type": "module"。
发生问题的是 ejs 模板文件,第一种方法肯定不能采用了;第二种方法经尝试仍然会报错
那把 Nodejs 降级到 14 以下的版本呢?
我下载了 12.22.12 版本的 Nodejs 进行覆盖安装。需要注意的是,用户目录 AppData 下 Local 和 Roaming 中的缓存文件夹 npm、npm-cache 以及 node-gyp 需要手动删除以防版本冲突。
结果还是失败了,无论是 require 还是 import 都会报错
这下思路断了
no-lodash
我开始失意地翻阅 Hexo 官方文档,在“变量”一节找到了这样一句话:
从 Hexo 5.0.0 开始,Lodash 已从全局变量中移除。迁移时 You-Dont-Need-Lodash-Underscore 或许能为你提供帮助
简而言之就是:既然用不了 lodash,那就把所有 lodash 的函数全换掉
不错!有够简单粗暴的!
接下来就是找出所有下划线并一个个换成等效函数的体力活了。不过这个项目中提供的都是只适用于数组的方法,object 相关的替换我是自己用 for 循环写的。于是 lodash 被我彻底踢出了这个主题
一个小插曲
Generate!
Error: Unknown output style "nested"
找到主题文件夹下的 _config.yml,把 node_sass 下的 outputStyle 属性删掉就行了
至此,bug fix 的环节算是告一段落了,我也把修改的部分提交了一个 PR ,希望能被 merge 吧
微调
clover 是 Clover Tuan 太太编写的,但是并没有注明使用的开源许可证,所以如果太太您在看并且觉得这样不合适的话还请告知
首页图标
太太在首页展示的默认图标有 Dribbble、Behance、Lofter、Instagram 以及 GitHub。那如果我想加点别的图标该怎么办?不如说这个首页图标究竟是怎么回事?
既然搞不懂,就去看看这究竟是怎么实现的。我直接简单粗暴地拿元素选择器框中了 GitHub 图标:

居然不是图片?逐一查看和它相关的 css,发现玄机藏在 source/css/font.scss 中:
@font-face {
font-family: 'iconfont'; /* project id 861369 */
src: url('//at.alicdn.com/t/font_861369_9voy0xmnmvl.eot');
src: url('//at.alicdn.com/t/font_861369_9voy0xmnmvl.eot?#iefix') format('embedded-opentype'),
url('//at.alicdn.com/t/font_861369_9voy0xmnmvl.woff') format('woff'),
url('//at.alicdn.com/t/font_861369_9voy0xmnmvl.ttf') format('truetype'),
url('//at.alicdn.com/t/font_861369_9voy0xmnmvl.svg#iconfont') format('svg');
}
.iconfont{
font-family:"iconfont" !important;
font-size:16px;font-style:normal;
-webkit-font-smoothing: antialiased;
-webkit-text-stroke-width: 0.2px;
-moz-osx-font-smoothing: grayscale;
&.icon-behance::before {
content: '\e919';
}
&.icon-lofter::before {
content: '\e63c';
}
&.icon-instagram::before {
content: '\e626';
}
&.icon-dribbble::before {
content: '\e6c3';
}
&.icon-github::before {
content: '\e799';
}
&.icon-arrow-left::before {
content: '\e91a';
}
&.icon-arrow-right::before {
content: '\e636';
}
}
经过一番搜索,我大致明白了原理:通过引用字体图标文件,让特定 Unicode 字符显示为图标的样子
明白了原理就可以开始动手了。找图标可以用阿里的在线字体图标服务 iconfont 矢量图标库,只要不商用一般也不会牵扯到版权问题
先注册一个账号,然后可以搜索自己需要的图标(因为太太的代码原因,请选择名称全小写的图标),添加入库:

挑选完图标之后,点击网站右上角带红点的购物车,选择添加至项目(没有项目可以新建一个):

此时会自动跳转到项目里面,点击“查看在线链接”并生成代码:

记下每一个图标的 Unicode 编号,可以点击“编辑”查看:


用生成的代码替换掉原来 source/css/font.scss 中的部分,每个图标也照葫芦画瓢地写如下一段:
&.icon-ICONNAME::before {
content: '\ICONUNICODE';
}
我的替换如下:
@font-face {
font-family: 'iconfont'; /* Project id 4356364 */
src: url('//at.alicdn.com/t/c/font_4356364_82dhsvzbmln.woff2?t=1701695612820') format('woff2'),
url('//at.alicdn.com/t/c/font_4356364_82dhsvzbmln.woff?t=1701695612820') format('woff'),
url('//at.alicdn.com/t/c/font_4356364_82dhsvzbmln.ttf?t=1701695612820') format('truetype');
}
.iconfont{
font-family:"iconfont" !important;
font-size:16px;font-style:normal;
-webkit-font-smoothing: antialiased;
-webkit-text-stroke-width: 0.2px;
-moz-osx-font-smoothing: grayscale;
&.icon-bilibili::before {
content: '\e600';
}
&.icon-github::before {
content: '\e799';
}
&.icon-rss::before {
content: '\e6d0';
}
&.icon-arrow-left::before {
content: '\e75b';
}
&.icon-arrow-right::before {
content: '\e75c';
}
}
来到主题文件夹下的 _config.yml,修改 social 部分的属性值:
social:
bilibili: https://space.bilibili.com/366719977
GitHub: https://github.com/image-builder-1837
RSS: /atom.xml
看看效果:

Done!
RSS
个人博客怎么能不支持 RSS 呢?好在 Hexo 配置 RSS 也不复杂,首先下载生成 RSS 的插件:
npm install hexo-generator-feed --save
在根目录下的 _config.yml 配置:
# Extensions
plugins:
hexo-generator-feed
#Feed Atom
feed:
type: atom
path: atom.xml
limit: 20
在主题文件夹下的 _config.yml 配置:
# RSS
rss: /atom.xml
这样就会在网站的 /atom.xml 下生成 RSS 订阅了(不知道为什么这里是乱码,我尝试在阅读器里打开是正常的):

可以在首页也加一个 RSS 的图标,具体的写法可以往上翻翻
其他
剩下的都是些微不足道的小改动,比如增加 mail 发送链接啦,增加 copyright 跳转链接什么的
结语
嗷嗷嗷终于写完了!单论个人博客的搭建其实并没有很复杂,主要是我选主题的问题(
咳咳,虽然搞七搞八地配置一大通确实挺麻烦,但完成的时候简直成就感爆棚!而且这几天搭博客也学到了一些奇奇怪怪的知识,比如在 GitHub merge PR 的时候要记得 squash and merge 而不是直接 merge(会让 commit history 变丑的!),又或者是一段关于 Javascript 模块化编程的历史等等。试想刚开始搭博客时怎么想到能扯到这些方面?也算是意料外的收获吧