自定义Hexo主题

从学前端开始貌似一直在折腾各种各样的博客,之前免费的云服务器快要到期了,加之最近用不了梯子,决定重新回到静态博客,于是重拾Hexo,打算将之前使用SSR搭建的博客主题移植过来,于是有了这篇博客,主要整理自定义Hexo主题以及使用Travis CI自动化部署的实践心得。

<!--more-->

参考:

其中主要参考了Next的样式,但Next的模板采用的是swig,这个我不是很熟悉,因此参考Hexo的默认主题landscape,使用ejs进行开发。最后的主题hexo-theme-shy放在github上面了。

1. 原理

回想一下Hexo的使用方法,非常简练

  • hexo new ,新增一篇博客,然后巴拉巴拉写一通
  • hexo g ,生成静态页面

可以发现博客原数据(文章)和主题样式是分离的,实际上Hexo会编译两次模板:

  • 第一次将markdown文档及其开头的Front-matter解析成一个对象,包含博客内容,此外还会统计分类、标签等信息
  • 第二次将所选主题(就是_config.yml里面theme配置项)的布局模板进行解析,并将第一次解析获得的数据填充到模板上,最后生成html页面

这方便我们将博客内容进行迁移(比如之前写的将Hexo博客数据迁移到Mysql数据库中),与此同时,开发主题也会轻松很多,因为我们不需要考虑去处理具体的数据,只需要知道Hexo提供的变量编写模板即可,因此开发主题的本质实际上是开发主题模板及对应的样式,

2. ejs语法

之前接触过一些模板引擎,ejs用起来跟laytpl比较相似,不过功能要强大一些(比如引入布局等)。学习ejs,最主要的就是掌握其中的表达式输出

  • <% %>,直接写变量或表达式,没有任何输出,一般用来定义变量或计算表达式
  • <%= %> ,通过=输出变量或表达式的值,输出的内容会进行HTML转义
  • <%- %>,与=比较相似,输出变量或表达式的值,输出内容不会进行转义

由于在hexo中我们只需要掌握对应的模板语法即可,ejs相关的api可以后面再去了解。

3. 开发

3.1. 新增自定义页面

首先使用hexo-cli新增页面

hexo new page test

然后发现在source目录下生成了对应的test/index.md,修改其Front-matterlayout属性,指定对应模板

---
title: test
date: 2017-10-14 22:38:14
layout: "test"
comments: false
---

然后在对应的主题layout目录新增模板即可,这里指定的模板名称是test.ejs

这里的一个问题是主题和页面产生了耦合,这是因为主题只能控制页面的展示,而无法控制页面的产生。

不过这也可以让用户自定义需要展示的页面,同理当使用其他的主题且想要增加自定义的页面时,也可以通过这种方式实现。

3.2. 变量的属性

文档里面只给出了全局变量和页面变量,但是对于单个变量比如tag并没有很详细的说明(也许是我没看见),所以采用最原始的console获取对应变量的属性

  • tag
    • name,标签名
    • length,标签的数量,可以用来制作标签云
    • path,跳转到对应的标签归档
  • category,跟标签基本类似
    • name,分类名
    • length,分类的数量
    • path,跳转到对应的分类归档

关于变量这点,确实还是自己搭后台要舒服一些,起码页面上知道能展示什么东西这些都是由自己掌控的。

3.3. 在theme目录中使用gulp

为了方便调试,直接hexo init了一个测试博客,然后直接在theme目录下进行开发,发现安装了node_modules目录后,hexo s等命令会非常卡,这个问题暂时没有找到解决办法,可能是与hexo-render插件有冲突

3.4. 修改代码高亮

自带的代码高亮比较蛋疼,还是使用hightlightjs比较熟悉,这里参考Hexo高级教程之代码高亮,记得先在根目录的_config.yml中关闭highlight.enable

这么做的缺点是在前端实现,体验不是很好,更好的做法应该是在解析markdown的同时配置hightlight,这需要修改hexo源码,

3.5. 修改配置文件无效

有时候遇见修改配置文件却无效的情况,比如上面关闭默认的highlight,需要使用hexo clean清除缓存

4. 部署

hexo内置了hexo d的插件,配合github Pages托管页面,可以快速部署博客,具体可参考文档

然而xxx.github.io项目下保存的之后hexo g编译后的文件,并没有托管博客的源码(就是source下面的markdown文件),之前在知乎上逛到了这么一个问题:使用hexo,如果换了电脑怎么更新博客?

排除掉用U盘备份等操作之后,一个可行的操作建立一个新分支或者重新建一个新仓库用于保存博客源码。那么问题来了,不论是新分支还是新仓库,每次更新博客的时候我们都需要提交两次,一次是源码,一次是编译后的页面,这样的重复工作感觉很麻烦。

此时可以采用自动化部署方案,比如说Travis CI

网上已经有了大量的教程来介绍“结合Travis CI和github Pages来托管博客”,我就不献丑了,简单总结进行的步骤:

  • 注册Travis账号,关联仓库(保存博客源码的那个仓库,不是xxx.github.io那个),然后配置github token
  • 当该远程仓库发生push等操作时(这是在关联仓库时选择配置的),如果存在.travis.yml的文件,则Travis服务器会执行该文件中预先编写的脚本
  • 我们可以在.travis.yml中编写需要执行的指令,比如npm i等,为了完成部署,我们需要自动执行hexo g,然后将编译后的文件推送到xxx.github.io仓库

关于.travis.yml的具体配置和语法,可以参考文档和对应的项目语言

实际上git本身还提供了git hooks,利用git的钩子脚本,我们甚至可以在每次本地提交之后自动推送到远程仓库然后利用travis完成部署。或者直接在本地自动使用hexo g生成文件然后推送到github pages上。

关于自动化部署,实际上可以牵扯出不少东西,包括之前折腾过的一点shell,这里感觉还需要深入了解一下,暂且按下不表。

5. 最后

想来想去也不知道这篇博客到底要表达什么,因为实际上我对hexo并不是很熟悉。想到去年五月份的时候,我的博客还是直接写HTML标签然后一个页面一个页面加链接的呢~

总是要折腾点什么,万一哪天用上了呢~

npm与一次版本更新事故 webpack折腾记(三)