Hexo博客踩坑笔记

Hexo提供了非常方便的Markdown写作方式,我们只需提供md文件,而Hexo则为我们生成个人博客并渲染md成为文章。因为生成的网页为全静态文件,所以可以很方便地部署到github pages上,省去了维护vps的麻烦。此文用来记录一些注意事项,就是我在部署博客时花费较长时间解决问题的笔记,方便日后参考。~~注意当前Hexo版本为3.2.0,主题NexT版本为5.1.3。~~Hexo版本更新到3.9.0,NexT更新到7.2.0。

写作

首页摘要

首页默认显示文章所有内容,文章长时很蛋疼,因此需要一个摘要功能。NexT有这样一个功能,可以选择摘取前面多少个字显示在首页。但是因为摘取的是md所以格式会错乱。NexT也建议我们使用more功能。
在文章某处加入<!-- more -->,那么此处前边内容会成为摘要,如果点击“阅读全文”则会在打开文章后自动定位到此处。

插入图片

一般用cdn,但考虑到我们内容并不多,所以我选择和文章放在一起。把配置文件post_asset_folder改为true,这样新建文章的时候会在同目录下有个同名文件夹,把图片放到文件夹里面。使用以下命令来插入图片。

1
{% asset_img example.jpg This is an example image %}

插入视频

  • Bilibili:使用iframe插入html5播放器。
1
<iframe src="//www.bilibili.com/html/html5player.html?cid=10156328&aid=6251621" height="400" width="100%"  allowfullscreen></iframe>

cid和aid的值需要打开视频并查看源代码进行搜索。
** 2018年1月更新:html5播放器链接失效 **

  • Youku:没有找到html5播放器,只好直接插入flash。
1
<embed type="application/x-shockwave-flash" class="BDE_Flash" src="https://player.youku.com/player.php/sid/XMTY2NTI1NTYyMA==/v.swf" width="500" height="450" scale="noborder" allowscriptaccess="never" menu="false" loop="true" play="true" womode="transparent" pluginspage="http://www.macromedia.com/go/getflashplayer" allowfullscreen="true" style="visibility: visible; display: block;">

在手机上则会空出一个500*450的区域,蛋疼。

2019年更新:建议直接放视频链接。

插入公式

NexT对数学公式提供了需要时才加载JS的解决方案。修改主题配置文件,启用mathjax.enablemathjax.per_page,在需要数学公式的md文件的front-matter中加入mathjax: true即可。

即使现在的版本,mathjax和hexo的解析依然存在冲突,最后的解决方法是使用下面的命令。

1
2
npm uninstall hexo-renderer-marked --save
npm install hexo-renderer-kramed --save

但是依然有残留的问题。Markdown会对部分符号\及后面一个字符进行转义,包括在公式内的部分也会先转义。所以要在公式中输入{,代码得是\\{,这样通过Markdown和Mathjax顺次解析后可以得到想要的结果。

站内引用

引用站内其他文章,可以使用绝对链接,也可以使用如下语法。

1
{% post_link 文章名 描述 %}

文章链接

文章链接默认是使用文章标题的,可能非常冗长,不好看,尤其是中文标题的文章。Hexo提供了一个Permalinks的功能,可以自定义文章的链接。可惜这几个选项,包括ID,都还是非常的长。

可选方案1:hexo-abbrlink

可选方案2:打开node_modules\hexo\lib\plugins\filter\post_permalink.js文件,在postPermalinkFilter函数的meta变量定义中加入一行date_abbr: data.date.unix().toString(36)。修改_config.ymlpermalink属性值为:category/:date_abbr/

可选方案2的解释:使用文章发布的时间(即front-matter中的date属性)缩写后作为链接内容。unix函数即将时间转换为unix时间戳(一个整数)表示,toString(36)即使用数字和小写字母的字符串表示这个整数。只要不同文章创建时间(秒)不同,文章链接就不会重复。

最近发现一个问题,就是文章分类更改的时候,评论区会重建,因为评论区是由链接来确定的。为了解决这个问题,我决定把文章链接改成:date_abbr/,即只与创建时间有关。索性进一步减少链接长度,把date_abbr改成了

1
Math.floor((data.date.unix()-1377964800)/3600).toString(36)

即以2013年9月1日(所有文章都在这个时间之后写的)作为起点,并以3600作为一个单位(保证一个小时内我不会写创建两篇文章)。

外观

底部文字

底部支持放置一行自定义文字,比如备案号。在主题配置文件的footer.custom_text可以定制。注意yml语法,最好外层加上单引号,比如:

1
custom_text: 'Hosted by <a href="https://pages.coding.me" style="font-weight: bold">Coding Pages</a>'

智能显示更新时间

新版的NexT已经支持此功能。

新版本的Hexo支持在md的front-matter处填写关键词updated,表示文章的最近更新时间,只要设置NexT主题中post_meta.updated_attrue就可以开启显示。问题在于post.updated在没有填写(或填写不合法)时会自动取值为当前系统时间(即最近generate的时间)。但我希望一次性写完的文章在页面时不要显示更新时间,之后有更新的文章才显示更新时间。为此经过多种尝试后我选择了一个最满意的答案:修改themes\next\layout\_macro\post.swig,通过搜索updated_at很容易找到两处,分别是输出“更新时间”四个字以及前面的分隔符。将这两处的逻辑加上一部分,and post.updated-post.date>24*3600*1000,意思是更新时间超过创建时间一天以上才会显示。这样每次退出修改md之前记得更新一下updated为当前时间就好了。能这么改是因为查看js源码(Hexo模块)可以知道post.updatedmoment对象,可以直接相减。

分类目录页面

点击参考链接即可。

404页面

需要自定义404的话,直接在source下新建404.md即可。记得把comments关掉。
设计404界面有两种方案,一种是把front-matter的layout设置为false,这样整个页面重新写过。第二种是我偏向的方案,即不这么做,继承原主题风格,只要写内容就行。但我发现在内容里面如果有标题(即<h1>之类的html标签),那主题会自动生成目录并展示给用户。这个目录就一个404,显然没什么用。
类似document.write("<h1">)的方法是可以解决问题,不过又尝试并得到了一种更满意的方案:

  1. 在404文件的front-matter中添加type: "404"。NexT主题原本是没有这个类型的,不要被网上一些代码骗了。另外注意这里的404是有引号的,不然被自动识别为数字类型。
  2. themes\next\layout\page.swigblock title部分添加(自行插入到合适位置)
1
2
#}{% elif page.type === "404" and not page.title %}{#
#}{{ __('404') + page_title_suffix }}{#

这样一来404页面如果不写title,不会影响html的title,从而页面上的大标题可以自己设计了。
3. 修改block sidebar部分为

1
2
3
#}{% if page.type != "404" %}{#
#}{{ sidebar_template.render(false) }}{#
#}{% endif %}{#

意思是只有非404页面才展示侧边栏。

评论系统

现在版本的NexT支持以下评论系统:

  • Hypercomments:国外的,访客可以留邮箱评论,支持很多社交账号登陆,但不包括任何国内的。
  • disqus:早就被墙了。
  • 多说:该评论系统已经关闭。
  • 畅言:之前一直在用的评论系统,鸡肋功能非常多,现在又要求访客评论前必须绑定手机号了。
  • Valine:改装Leancloud得到的评论系统,目前尝试效果还行,不能用社交账号登陆,验证码有点鸡肋。
  • 友言:以前用过,服务器不太稳定,支持的社交账号比较少。
  • LiveRe:韩国的,没试过。
  • gitment:需要github账号,国内不算方便。

Valine

目前我使用的Valine,但是themes\next\layout\_third-party\comments\valine.swigel: '#vcomments'应修改为el: '#comments',原理是Valine通过查找ID为comments的Element来加载部件。这里怀疑是笔误,不知道为什么之前没有人发现。作者已经接受我的Pull Request了,以后应当没有问题。
建议关闭验证码和邮件提醒,因为验证码是用JS生成文字的,基本没有用,而邮件提醒在没有验证码的情况下容易出问题。

LiveRe

中文叫来必力。可能因为是韩国的(语言障碍,没有别的意思),可能因为中文名不好听,我在尝试了其他所有选择之后才想起看看这个,目前发现效果真的好,不会被墙,支持中国的很多社交账号,而且规模也很大不担心不稳定。所以删掉上面的,改用这个啦。

gitment

既然内地网络访问github多数还好,所以评论就换成了gitment。注意gitment现在需要自己搭建一个gateway,参见手记4手记6。简单地说就是寻找一个支持PHP和HTTPS的服务商,把intersect给clone下来,填好DOMAIN_ACCEPTPRIVATE_CLIENT_SECRET后放到支持服务器根目录上(尤其注意.htaccesscacert.pem两个文件都要放过去),再把服务器的域名(包括前面的https)填到NexT选项里的proxy_gateway中即可。

gitalk

NexT新版支持gitalk,原理和gitment类似,但是不用自己搭gateway了,所以用这个。

文件压缩

Hexo自动生成的文件留白很多,去掉的话能节约空间、减少传输时间,使用hexo-all-minifier一步到位。据说这个东西会去掉全角TAB,不过我们缩进也用不到这个,所以无所谓。

部署和双线路解析

考虑双线路是因为部署前看到了这篇文章,怎么做里面已经说的很清楚了,不过deploy部分还需要根据新版本作出修改:

1
2
3
4
5
6
7
deploy:
- type: git
repo: git@github.com:Aqua-Dream/aqua-dream.github.io.git
branch: master
- type: git
repo: git@git.coding.net:fmyl/fmyl.coding.me.git
branch: master

我是用阿里云解析,加两条,分别是默认线路和海外线路的CNAME即可,但是默认的线路加不上,提示冲突,把其他解析都删掉,最后TXT解析也删掉,才行。注意coding的解析地址可以是page.coding.me

Coding有https证书功能,申请的时候,需要读取域名下的文件,结果可能因为coding不是内地服务器(好像是香港的?),解析到github上导致读取不到需要的文件。后来想了想,干脆就直接用coding好了,想来国外的访问速度也不会很慢

博客的各个方面都必须为中国的GWF做一些特殊处理,这是因为我写的是中文,受众自然应该是国内用户,应该把他们的感受摆在第一位。(其实只有我一个用户??)

2019年更新:回到内地发现github速度还可以,coding速度也不咋地,干脆直接用github好了。

SEO

Sitemap

1
2
npm install hexo-generator-sitemap // Google 
npm install hexo-generator-baidu-sitemap // Baidu

在config最后新增

1
2
3
4
5
sitemap:
path: sitemap.xml

baidusitemap:
path: baidusitemap.xml

提交sitemap前注意:部分页面不想被收录的需要在front-matter前加sitemap: falsebaidusitemap: false,比如404页面,比如站点确认文件等等。
此外我在config中设置网址为//开头,即没有指明协议,这样生成的sitemap中网址也是//开头,结果不能被google识别,所以需要写上协议才行。

主动推送

百度主动推送链接

分享功能

百度分享和JiaThis都不支持https站点。有人针对百度分享做了改进,点击查看解决方案
此外可以使用needmoreshare2,NexT主题已有包含,但微信加载二维码的API挂了,需要自己修改。方法见其issue。用qrserver的服务即可。

这个功能实质上不是微信分享,而是一个生成网址二维码的API。现在微信开放的接口需要企业认证,比较麻烦,只能选择这种方法进行替代了。