简介
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’) 是不考虑时区偏移的?实测结果是等于原始指定的文本
- 指定日期文本后,hexo将日期文本解析为momentjs对象,包含时区偏移,所以日期的数字不一定等于文本的数字,比如文本 2018-02-25 00:00:00 -> momentjs对象(2018,02,24,23,00,00,+7)
内置辅助函数
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