Hexo博客搭建记录
2021-03-18

简介

Hexo一个基于Nodejs的静态博客框架,通用预定义的模板和内嵌变量将Markdown文档渲染为静态网页

本博客就是使用Hexo搭建的,并且自行开发了主题

通过官方文档API手册,即可搭建和编写简单主题,但有些配置和细节文档中没有描述的很清楚,这里主要记录了博主搭建博客和编写主题、使用插件的过程

Nodejs通过npm来管理模块/包,包目录下的package.json记录的包的名称、版本和依赖包(dependencies)等信息,安装的包在node_modules中

对于hexo,在一个目录(下面称为博客目录或博客)初始化后就产生了一个包,这个包里的package.json还有一个特殊项hexo,指定了hexo的版本,一般不需要手动修改package.json

通过npm可以安装主题和插件(主题和插件本身也是一个个包,作为博客包的依赖)

dependencies中可以看到一些默认安装的官方插件

"hexo-generator-archive": "^1.0.0",
"hexo-generator-category": "^1.0.0",
"hexo-generator-tag": "^1.0.0",
"hexo-renderer-swig": "^1.0.0",
"hexo-renderer-stylus": "^1.0.0",
"hexo-renderer-marked": "^4.0.0",
"hexo-theme-landscape": "^0.0.3",
  • renderer是渲染器,从一种文件格式得到另一种文件格式

    • swig / markdown -> html
    • less / sass / stylus -> css
  • generator是页面生成器,通过调用hexo的api,根据某个特定的模板,在特定的路径下生成页面

  • theme是主题,默认安装landscape主题

博客的配置在_config.yml文件中,hexo渲染过程中,主题、插件可以读取配置的中的配置项

博客目录下的scripts子目录可以放置一些js脚本,通过hexo的api介入渲染和生成过程,类似于插件,如果要实现一些自用的功能,而不需发布为插件,则不用建立一个单独的包,直接添加到该目录下即可,渲染时

博客目录下的themes子目录也可以放置手动下载解压的主题

博客目录下的source子目录存放博客源文件,_posts目录中markdown格式文件会被渲染,而其他文件直接复制到public,具体规则可以在配置中控制

博客目录下的public子目录存放生成的静态页面文件

配置

  • 配置中的永久链接格式permalink: ,可以用一些预定义变量,对于文章的路径

    • :title包括了相对_post的路径
    • :name才是纯文件名
  • 可在配置中添加以下,来开启hexo server时的gzip压缩

    • 官方文档里没有提及,但打印hexo.config对象可以看到默认配置
    • 开启后在调试时使用浏览器控制台的lighthouse作性能评估时就不会提示启用文本压缩这一项了
    server:
      compress: true
    

渲染器

渲染器插件实际上只是对真正的渲染引擎作简单的包装,通过hexo的APIhexo.extend.renderer.register注册文件映射,调用真正的渲染引擎渲染,

比如hexo-renderer-less插件,实际调用less进行渲染

模板

模板的默认渲染器是ejs,即主题的layout目录下应该都是.ejs文件

也可以换成swig,jade,pug等

只能安装一种,否则可能会有冲突

npm install hexo-renderer-ejs --save
npm install hexo-renderer-swig --save
npm install hexo-renderer-jade --save
npm install hexo-renderer-pug --save
样式

样式的默认渲染器是stylus

可以安装less或sass渲染器

npm install hexo-renderer-less --save
npm install hexo-renderer-stylus --save
npm install hexo-renderer-sass --save

对于less插件,自定义渲染的文件路径和less配置项,需要在主题的配置中修改,如themes/yourtheme/_config.yml

less:
  paths: ["/[主题的]source/css", "/[主题的]source/css/*", "/[主题的]source/css/style.less"] //会转换到public对应的css,下划线开头的子文件夹不会处理
  options: //会直接传给less
    compress: true
markdown

markdown的默认渲染器是marked,会对$$内部公式进行默认转义导致mathjax解析失败

kramed是在marked基础上修改的,支持了数学公式以markdown中的原样输出

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

但其实还是有小问题,比如 $a_b^c,C_{linear}$中间两个下划线之间的内容会被当成斜体

最后还是在主题中写了脚本通过api在渲染前提前替换,渲染后再替换回去

生成器

默认的几个生成器的生成规则如下

archives

生成后有一个总主页 /archives/

每年有一个主页 /archives/[year]

每月有一个主页 /archives/[year]/[month]

它们都由archive.ejs生成,可在模板内判断is_archive, is_year, is_month

tags

每个tag有一个主页 /tags/[tag],由tag.ejs生成

没有总主页,需要自行补充!

  • 方法一:在source中,添加tags目录并在其中添加文件index.md
    此时是用普通的布局page.ejs生成,可在其模板内部通过路径page.path === "tags/index.html"
    page.source === "tags/index.md"作特殊判断

  • 方法二:在layout里新建一个布局tags.ejs(内容自定,可以用变量site.tags获取所有标签),然后在scrips里添加一个generator脚本,注册

    hexo.extend.generator.register('tags', function(locals){
        return {
            path: '/tags/index.html',
            layout: ['tags'],
            data: locals.theme
        };
    });
    

注意:标签插件是用于在markdown中引入新的语法标记,和这里文章的分类标签不是一回事,另外,本博客及主题不打算使用标签插件,因为这会引入非标准markdown语法,不便于以后迁移

categories

类似tags

一些有用的插件

图片路径问题

修改博客配置的post_asset_folder: true,这样每篇文章都使用独立的资源文件夹(即hexo new [title] 时会创建同名文件夹)

但如果在markdown中按一般方式(即相对于独立资源文件夹的路径)引用图片,在渲染后的文章页能看到图片,在主页的文章预览中很可能看不到相对路径图片,需要安装以下插件

npm install https://github.com/7ym0n/hexo-asset-image --save
搜索

静态博客无法通过与服务器交互查询来搜索指定文章,只能在渲染时生成所有文章的一些元信息保存为JSON,在页面加载中通过JS载入,用户搜索时直接从JSON中获取,下面这个插件可以实现

npm install hexo-generator-search --save

博客配置添加

search:
  path: search.xml 或 search.json
  field: post
  content: true

加上content后可以实现全文搜索,但可能导致JSON文件过大,页面加载时间变长

SEO

通过添加网站地图即sitemap,向搜索引擎提供网站的页面位置信息

npm install hexo-generator-sitemap --save
npm install hexo-generator-baidu-sitemap --save

博客配置添加

sitemap:
  path: sitemap.xml
baidusitemap:
  path: baidusitemap.xml

sitemap是官方插件,不过好像没有处理配置中root不是/的情况

baidu-sitemap是第三方插件,没有包括tags/categories页面,但处理了root不是/的情况

另外,可以在博客source根目录添加robots.txt文件

User-agent: *
Allow: /
Allow: /archives/
Allow: /tags/
Allow: /categories/
Allow: /page/

Disallow: /js/
Disallow: /css/
Disallow: /img/

Sitemap: /sitemap.xml
Sitemap: /baidusitemap.xml
高亮

关闭hexo默认的高亮引擎,本博客是在主题中实现高亮

highlight:
  enable: false
prismjs:
  enable: false
GIT部署

如果在渲染后需要一键部署到github,可以安装插件

npm install hexo-deployer-git --save

博客配置添加

deploy: 
  type: git 
  repo: https://github.com/用户名/用户名.github.io.git 
  branch: master

执行

hexo d

此时会在博客目录下生成.deploy_git目录(内容同public目录),即git仓库,会被强制push到github上

主题与插件开发

主题是一个单独的包,包括几个目录

layout目录,存放模板文件,会被博客全局注册的生成器或者主题内注册的生成器使用

scripts目录,类似全局的scripts目录,调用API或实现自定义功能,如

  • 注册生成器
  • 注册渲染前后的事件监听,实现对渲染过程的控制,如渲染前替换所有的数学公式

source目录,包括网站发布需要的一些样式和脚本文件,样式可以是原始的css,也可以是less等(会经过全局注册的渲染器生成css)

模板

主题的layout目录下存放了各种模板,它们会被注册的对应生成器读取,通过渲染器,加上hexo的内部变量,如文章的信息和配置项等等,最终生成静态页面

在模板中,通过内置的上下文变量和一些辅助函数,可以实现自定义生成页面的内容和样式

内置上下文变量

全局变量:即所有页面中都可访问的变量,官方表格如下

变量 描述 类型
site 网站变量 object; 见 网站变量
page 针对该页面的内容以及 front-matter 中自定义的变量。 object; 见 页面变量
config 网站配置 object (站点的配置文件)
theme 主题配置。继承自网站配置。 object (主题配置文件)
path 当前页面的路径(不含根路径) string
url 当前页面的完整网址 string
env 环境变量 ???
网站变量site

site.posts 即所有文章 指放在_post文件夹下的md文件
site.pages 即所有分页 指放在_post文件夹外的md文件

页面变量page

在不同类型(page/post/index/archive/tag/category)的页面中,页面变量page包含的属性是不一样的,具体参考官方文档

注意:每一个页面都有一个变量叫page,同时,有一种布局或者说页面类型叫page(意为普通的页面,相对的post/index/archive/tag/category是特殊的页面类型),不要混淆了哦

其他注意
  • 内置的数组变量,如site.posts并不是真的Array,而是一种对象,

    • 有data和length属性,data才是Array(可用forEach),
    • 有each方法,回调函数function(obj, idx){}
  • 对于site.posts的每一个post对象,post.date即文章的日期,若不在markdown文件的头部元数据中指定,则默认为文件的创建日期

    • 指定日期文本后,hexo将日期文本解析为momentjs对象,包含时区偏移,所以日期的数字不一定等于文本的数字,比如文本 2018-02-25 00:00:00 -> momentjs对象(2018,02,24,23,00,00,+7)
      momentjs对象.format() -> 2018-02-24 23:00:00
    • 渲染时,使用hexo自带辅助函数格式化 date(post.date, ‘YYYY-MM-DD’) 是不考虑时区偏移的?实测结果是等于原始指定的文本
内置辅助函数

url_for(page.path) 会补上path里缺少的root部分(如果root是/,则没有变化)

API

可在博客的scripts或主题的scripts目录下添加JS脚本,调用hexo的api,改变渲染过程

hexo是个全局变量,是Hexo类的实例,在脚本里console.log打印就能得知有哪些属性

一些有用的属性

  • xx_dir各种路径

    base_dir: '[path to you blog]\\',
    public_dir: '[path to you blog]\\public\\',
    source_dir: '[path to you blog]\\source\\',
    plugin_dir: '[path to you blog]\\node_modules\\',
    script_dir: '[path to you blog]\\scripts\\',
    scaffold_dir: '[path to you blog]\\scaffolds\\',
    theme_dir: '[path to you blog]\\themes\\[theme name]\\',
    theme_script_dir: '[path to you blog]\\themes\\[theme name]\\scripts\\',
    
  • hexo.config是全局配置,是_config.yml文件内容的JSON表示,包括未在配置文件中指明的一些默认配置

  • hexo.theme.config是主题配置,好像只在 回调函数中才能读取到,脚本全局的访问不到(可能此时未加载主题配置)

  • hexo.locals是“局部变量”,其实就是上面模板里的全局变量site,可通过get/set获取和修改某个变量

    • 比如hexo.locals.get('pages')相当于模板里的site.pages
  • set方法的参数是一个回调函数

  • hexo.*.context == hexo*包括source,render, theme等等)

  • hexo.extend.*.register(callback) 系列(*包括filter,generator,renderer等等)注册的回调函数中,满足this == hexo

搜索
背景设置