博客迁移到了Hexo(附折腾记录)

四年沉寂,重新出发,将博客从Octopress 迁移到了 Hexo。

记录下迁移的过程,以及Hexo的坑点。

源起

大学临近毕业的时候,发现了Octopress,就兴冲冲用Github pages建了自己的博客。

还没写两篇文章,一入职,就忙起来了,从入职培训,到后来项目赶着上市时不停的加班……

我本就是懈惰的人,加之公司安保极严,在公司的成果无法带出,加班之余便再无更新,以至荒废。

眨眼四年过去,工作内容渐渐从新鲜有趣变成了单调重复,也觉得自己不适合通信硬件行业(软件岗,但是围绕硬件开发OS),心一横,裸辞了。美其名曰,在家充电。

四年里深深体会到留下文字记录的重要性。软件这行,涉及知识之多,更新之快,以我等凡人,哪怕自己踩过的坑,当时再刻骨铭心,事后回忆根本记不得细节,半天最多拼凑出一点线头,乱扯一通,平白多了许多无用功。

在家面壁的第一件事,就是博客重开。如果说当年年少naive,存有一点虚荣,希望写文能得到关注;那么现在纯粹是为自己做个记录。至于有没有别人看,倒是一点不重要了。

像我还在公司时,偶尔折腾一些新鲜且实用的技术做分享,最终发现感兴趣的人寥寥无几 —— 一些人觉得跟他业务无关,一些人觉得这太难懂,一些人觉得这太显浅……

以后关于技术上的经历,尽量事无巨细在此记录;在老东家闲时研究的一些跟商业秘密无关的东西,我也会尽量回忆出来整理在此。

Hexo

四年里面,笔记本已经换过了。重新翻出Octopress ,实际上已经不能跑了,还得重新配置一遍。想当初有些gem需要Devkit编译,又麻烦又慢,坑不是一般的多。关键当初记录这些坑的博文还没写完……

这种情况下,发现了Hexo。

说到底,用Github-pages 搭博客,要的是静态HTML+js。然而总是手动写当然效率低,Octopress 不过提供了工具和模板,从Markdown 生成HTML。
这样的事,Hexo干得也差不多,而且因为基于Node.js,不像Octopress涉及那么多语言,配置容易太多了,速度快太多了。(没记错的话,入口是Ruby,有些gem基于C++所以要编译,代码高亮貌似Python,而页面渲染,一定有引用js的库……真是大杂烩)

当然并不是Octopress 就不好了,从Hexo 主页的描述来看,Hexo作为后来者,借鉴了很多Octopress 的优点,同时躲开了很多Octopress 掉了的坑。

How-to

注意!! 在当前这个时间点(2016-06),Hexo 还有大量的提交,我以下说的内容,随时可能因为版本的迭代而过时。

Hexo 依赖两个东西

  • Node.js
  • Git

关于Node.js 的安装,我前面一篇关于 nodePPT文章有介绍,不再赘述。Git 的话我也想整理一些文字,不过在那之前,网上相关的信息也非常多,应该很好解决。

有了这两个东西之后,安装Hexo无非就是一行命令:

1
npm install -g hexo-cli

其实,这些内容,甚至包括Git 和 Node.js 的安装,官方文档都有简要提及,甚至连从Octopress 迁移都有对应说明。所以官方文档有提到的我都不说了。hexo 初始化之后会自动生成一篇以 hello world 为题的文章,我把它挪到了这里 ,大家可以参考一下。后面主要记录一下遇到 / 我觉得可能有人会遇到 的坑,以及补充官方文档不够详尽 / 显眼之处。

Updated: 以下安装插件的代码,都要在执行过hexo init 的博客目录下执行一遍。原因参考下面『在其他电脑配置已有的博客』章节。

任意目录运行hexo

概述页面的评论有人问,成功安装之后,报这个错误

1
‘hexo’不是内部或者外部命令,也不是可运行的程序或批处理文件

明眼人一看就知道是path环境变量的问题,解决办法就是把node的安装目录加入环境变量。如果这样都还不知道怎么办,详细设置请看 nodePPT那篇文章

语言配置

文档只告诉你可以配置语言,但是并没有告诉你有什么语言可以选,也没告诉每个语言对应的值

譬如像我这种长期写Android 代码的,就会习惯性写 zh-rCN

实际上语言文件在 themes\<主题>\language\ 下面

我暂时不折腾,用默认的 landscape 主题我现在使用基于landscape改动的landscape-plus,那么对应简体中文的配置就是 zh-CN

Octopress 的 Categories V.S. Hexo 的 Tags

在Octopress 如果要增加标签来分类,用的是

1
categories: [tag1, tag2, tag3]
  • tag1
  • tag2
  • tag3

然后在每个标签下,都能找到这篇文章

文章迁移到了 Hexo 之后,效果就变成了嵌套关系

  • tag1
    • tag2
      • tag3

原来Hexo 将分类功能细化成了 分类 和 标签,原来的 分类 功能有了层次关系,譬如

  • 中国
    • 广东省
      • 广州市

如果想像以前那样用互相独立的标签,Hexo 的用法是

1
2
3
4
tags:
- tag1
- tag2
- tag3

关于Git

部署时关于Git的问题,其实官方文档-部署是有提到的。然而还是看到网上很多人会问,所以我把关于安装相关插件和相关命令的章节链接放这里。估计多数人是漏了安装 hexo-deployer-git 这个插件。可以通过以下命令安装

1
npm install hexo-deployer-git --save

另外,如果你像我一样用Windows,平时用的Gitbash,部署时会报一些错。

那是因为Gitbash启动时会加载一些参数,这些参数在cmd下是无效的,你得重新配置一次。

所以最好的办法是,你直接在Gitbash下运行hexo。

关于Disqus(或国内的多说) 与 主题

我本来一点不想折腾外观的东西,能用就行,但评论功能无论如何是需要的。

然而我并没有找到配置的地方,也记不起当初Octopress 怎么配置。于是去看了Disqus 的说明,发现只要加一个对应的<Div>加载js,提供shortname 和 当前链接 两个参数即可。

于是想在主题里加,翻了半天不知道在哪加好。然后看别人的主题都有评论,心想算了,还是换个主题吧,顺便换个对中国本土优化过的主题也好。改虽说不难,但改好看也不简单,不想在小事上费神。

看了半天,算是对 NextJacman 两个主题比较感兴趣,但试用效果并不是我想要的,最终换回了基于官方主题 landscapelandscape-plus,_config.yml里写明支持 多说

这里提醒大家,知乎上有关于Hexo主题的讨论,总结得挺好,至少比官方那几个主题候选强多了,大家可以去看一下。

我想既然支持多说,disqus应该没问题吧,就搜了一下源码,发现加载位置原来在 after-footer.ejs ,果然也支持disqus,只是没提。

因为 landscape-plus 基于 landscape,我猜其实一开始就支持disqus了,就去翻源码,果然… 无端绕了一个圈,应该一开始就搜源码…就当见识一下其他主题吧,而且现在的主题虽然样子没变,对本土优化过也不坏。

实际上就是 _config.yml 里一行的事:

1
2
3
4
# Disqus
disqus_shortname: your_dqs_sn
# Duoshuo
duoshuo_shortname: your_ds_sn

几个要点:

  • landscape 只支持disqus
  • landscape-plus 同时支持 disqus 和 多说,但是都配置的话,优先加载多说,然后忽略disqus
  • 代码一眼就懂,只要知道位置就能自己动手修改:themes/<theme_name>/layout/_partial/after-footer.ejs,其他主题应该也类似
  • shortname 的配置写在主题的 _config.yml, 得写在全局配置,至少我是这样。估计是因为引用时是 config.disqus_shortname 而不是 theme.disqus_shortname

Updated: 我提了一个PR给landscape-plus,现在无论写在主题还是全局的配置,都可以加载。

关于插入HTML代码 与 Hexo 的换行

习惯使用 Markdown 的朋友知道,Markdown是支持直接写HTML代码的。

这点带来了很大的方便:Markdown 足够小巧简洁,满足大多数需要;一旦有超出支持范围的需求,大可临时写一下HTML。

但是,这点在Hexo,好像突然不满足了。我插入的HTML,变成了一堆很奇怪的东西。

翻生成出来的HTML,找到原因:hexo 在我每一行代码后面,都插了一个<br>…… 我回去再翻我的md文件,行末并没有两个空格。由此我发现了 Hexo 与官方 Markdown 的一个差别,就是Hexo 为了你写文章方便,不需要你行末加两个空格,都会给你一个<br>

然而这点让我自己插入的HTML(准确说是MathML)成了这样:

1
<mrow><br> <mi>x</mi><br> <mo>=</mo><br> <mfrac><br>...

多了这么多<br>根本不能好好地被解析。

然后发现官方的处理方法是,加raw标签

1
2
3
{% raw %}
some raw content
{% endraw %}

在里面的内容,会原样输出。详细说明在官方文档这个地方

404页、about页

404页我直接用了腾讯的404公益的代码,就是随便写一个最基本的HTML,然后在body部分加载以下js即可

1
<script type="text/javascript" src="http://www.qq.com/404/search_children.js" charset="utf-8"></script>

后来因为腾讯公益的404会替换整个页面,而且无法提供https的链接,我又改为使用益云的404了。

hexo/source 下创建 404.md

1
2
3
4
5
6
7
---
title: 抱歉,你要访问的网页没有找到...
---
{% raw %}
<!-- 你的益云404代码 -->
{% endraw %}

至于about页,可以直接

1
hexo new page about

然后修改 /source/about/index.md 即可。跟写博文一样,最后生成出统一风格页面。

由于毕竟不是博文,提醒

  1. 删掉时间
  2. 不要添加categories或者tags

使用自己的域名

首先要买一个域名。

这部分占个坑,有空补完…

atom 和 sitemap

该章节参考了Hexo搭建Github静态博客

分别要安装对应的插件

1
2
3
npm install hexo-generator-feed --save
npm install hexo-generator-sitemap --save
npm install hexo-generator-baidu-sitemap --save

稍微解释一下 --save 参数。有这个参数的情况下,对应的module会作为依赖自动写入当前目录的 package.json 。我是在 博客的根目录下执行的,那么会自动添加依赖。详情可以参考npm 常用命令详解

然后在 根目录\_config.yml 添加以下内容来启用插件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Plugins:
- hexo-generator-feed
- hexo-generator-sitemap
- hexo-generator-baidu-sitemap
#sitemap
sitemap:
path: sitemap.xml
baidusitemap:
path: baidusitemap.xml
#Feed Atom
feed:
type: atom
path: atom.xml
limit: 20

如果想在导航上显示,可以在主题的 _config.yml 中添加 (最后两行是新增内容)

1
2
3
4
5
6
7
8
9
# Header
menu:
Home: /
Archives: /archives
Github: https://github.com/xxx
About: /about
Sitemap: /sitemap.xml
# Baidusitemap: /baidusitemap.xml #这个主要是针对百度做过优化,更好被百度抓取,但是导航上没有必要显示两个
rss: /atom.xml

在其他电脑配置已有的博客

2016/12/26 updated:

到了新岗位之后,发现在公司电脑也有更新博客的需求——在公司踩了的坑,要赶紧记下来,回家再写可能就忘了,而且到家太累有时也不愿意开电脑。

这个博客的源码放在我个人的笔记本上,生成的静态页面自然是通过git push到了github pages 上(也就是现在看到的页面);源码我也用git管理着,push到了 bitbucket 的私人库上。在我的想象里,在公司电脑写hexo的步骤是:1. 安装node.js 和 hexo-cli ;2. git clone bitbucket 的源码;3. 跟在个人笔记本上一样,写完 hexo g -d

我甚至都没验证一下,直接就操作了,结果一刷新,博客无法访问了!!仔细看public文件夹,发现根本没有处理,而是直接把source文件夹的内容拷贝过来而已。

这我才开始琢磨,发现博客目录下的 node_modules 目录是存放引用的node包的,而且是在init之后,安装,且只安装在这里,并非global。而自带的.gitignore 里是包括 node_modules 的,换言之源码的提交并没有包含它,git clone下来当然也会缺了对应的包。

那是不是改掉 .gitignore ,把这个目录页提交掉呢?我认为并不是,因为安装前后的时间差异,我两台电脑的node.js 和 hexo-cli 的版本并不一致,所以依赖的包的版本,乃至依赖的包都可能不一样,直接用同一个 node_modules 不一定能正常运行。所以我最后解决的办法如下:

  1. 首先当然要确认新电脑 node.js / npm / hexo 已经安装配置好,可以任意目录执行。
  2. 新建一个空的博客的根目录,在里面 hexo init,让它安装基本的依赖。
  3. 上面提到需要的插件安装,都在这个根目录下执行一遍(就是那些带 --save 参数的)。
  4. 另起一个目录,把源码clone下来,然后全部覆盖到上面init 好的目录。
  5. 另起一个目录,把github pages 的库clone下来,然后覆盖到.deploy_git 目录。这步是为了让提交历史连续,对于成功发布不是必要的。
  6. hexo g 观察一下 public 目录的输出,没问题再 hexo d。有任何问题,检查上面几步。

移动也会出错

updated: 2017-1-4

上面说到,通过远程库的方式,在新电脑clone之后,因为node_modules目录被ignore掉了,所以不能正常运行,要重新init 和 安装插件。

今天整理本地目录,将博客的目录挪了位置,忽然发现也不能运行了。按说这个目录一起移动,node_modules里的东西都还在,不应该有什么问题。更神奇的时候,因为hexo-cli 是global安装,所以任意目录都能运行hexo,除了博客目录。

试验之后发现,虽然 init 时安装的依赖,是直接安装到node_modules下(如hexo-generator-archive,就是直接安装到同名目录下);

但是加了--save参数手动安装的插件,安装方式却有所不同。那些插件是先安装到了一个带版本号的目录,然后再产生一个插件名(不带版本号)命名的软链。如abab,是先安装到.1.0.3@abab目录,然后再生成一个 abab 到该目录的软链。

问题就出在这个软链上。看得出来软链的本意是方便指向不同的版本。但因为软链是基于指向目标的绝对地址的,所以一旦挪动了目录,哪怕是一起挪动,相对路径不变,软链也会失效。而运行hexo 时,会根据根目录下的package.json去找依赖,手动安装的插件当然也在依赖之列;接下来会按名字寻找,找不带版本号的目录(其实是软链),因为软链失败,自然依赖检查也会出错。

由于init时安装的依赖没有问题,所以解决这个问题,只需要删掉那些带版本号的目录和相应的软链,然后重新手动安装插件就好。


未完待续…

其他发现的坑,也会陆续更新在这里。


知识共享 “署名-非商业性使用-相同方式共享” 4.0 (CC BY-NC-SA 4.0)”许可协议
本文为本人原创,采用知识共享 “署名-非商业性使用-相同方式共享” 4.0 (CC BY-NC-SA 4.0)”许可协议进行许可。
本作品可自由复制、传播及基于本作品进行演绎创作。如有以上需要,请留言告知,在文章开头明显位置加上署名(Jayce Chant)、原链接及许可协议信息,并明确指出修改(如有),不得用于商业用途。谢谢合作。
详情请点击查看协议具体内容。