Hexo 简介

Hexo 是一个快速、简洁且强大的静态博客框架,基于 Node.js 开发,允许用户使用 Markdown 语法 编写文章,并将其转换为 HTML 页面,部署后呈现为个人或企业的 web 站点。

建站

  1. 安装 Node.js:访问 Node.js 官网,下载并安装
  2. 安装 Hexo:在命令行中,通过 npm 命令安装 hexo
    1
    npm install -g hexo-cli
  3. 初始化 Hexo 站点:在命令行中,使用 hexo 命令创建一个博客
    1
    2
    3
    hexo init blog
    cd blog
    npm install
  4. 启动 Hexo 站点:使用 hexo 命令启动本地预览,通过 http://localhost:4000 即可访问
    1
    hexo server
  5. 新建文章:使用 hexo 命令创建一篇名为 article.md 的文章
    1
    hexo new post article
  6. 生成静态文件:使用 hexo 命令生成静态 html 文件
    1
    hexo generate
  7. 部署网站:
    1
    hexo deploy

Hexo 支持的各条指令和使用方法,请参考 Hexo 官网的 命令说明

配置

当初始化站点执行成功后,进入站点目录,可以看到如下内容:

.

├── _config.yml # 网站配置信息

├── package.json # 程序使用的工具和库文件信息

├── scaffolds # 存放网站使用的模版文件

├── source # 存放用户资源,如文章、图片等

| ├── _drafts # 存放未发布的草稿

| └── _posts # 存放正式发布的博文

└── themes # 博客使用的主题

网站配置项都包含在_config.yml 文件中,各配置项的含义,请参考 Hexo 官网的 配置说明

常见的个性化定义的配置项包括:

参数 含义 默认值
title 网站标题
description 网站描述。主要用于 SEO
keywords 网站关键词
author 网站作者
language 网站语言。中国大陆使用zh-CN
timezone 网站时区。中国大陆使用Asia/Shanghai
permalink 文章永久链接格式。为了优化 SEO,建议缩短长度 :year/:month/:day/:title/
theme 使用的主题名称。为 false 表示禁用主题
deploy 部署环境配置。常见的有 Github

Hexo 主题

对于前端零基础、审美也堪忧的人来说,从空白雕出一个漂亮的网页 UI,那是不可能的,好在 Hexo 提供了丰富的 主题

通过预览找到心仪的主题,记住主题的名称,然后到 github 上用 hexo-theme-$name 搜索,即可找到主题对应的代码仓。为什么 Hexo 主题预览页不直接提供对应的 github 仓库的链接呢,令人费解 o(╯□╰)o。

关于主题挑选,从审美上来说,萝卜青菜,各有所爱;从可用性来说,建议选使用者还算多的,代码仓还有人维护的。不同的主题切换,还是需要一些适配成本的。

我选的tranquilpeak,用的人不算少,但是作者好像已经不怎么维护和更新了。导致有一些功能需要自己开发和改造,过程中免不了踩一些坑,这也是本篇博文诞生的主要原因。

后续改动都是基于 tranquilpeak 主题,其他主题不一定能拿去即用,解决方案仅供参考。

安装

根据 tranquilpeak仓库说明,tranquilpeak 的安装和启用包括以下步骤:

  1. 下载 最新版的 tranquilpeak
  2. 解压后,放到 Hexo 博客主目录下 themes 文件夹中
  3. 修改 Hexo 博客主目录下 _config.yml 文件中 theme 参数,设置为tranquilpeak
  4. 进入 Hexo 博客主目录下 themes\tranquilpeak 文件夹中,执行命令:
    1
    npm install && npm run prod

配置

themes\tranquilpeak文件夹中也有一个 _config.yml,这个文件中的配置项会覆盖 Hexo 博客主目录下_config.yml 的同名配置项。

tranquilpeak 主题的配置方法参考 仓库说明

本博客站点设置的一些 tranquilpeak 主题配置如下:

配置项 含义 取值 说明
location 位置信息 中国 中国
picture 个人头像 photo.jpg 位于source\assets\images
github github 用户名
sidebar_behavior 侧边栏的呈现 2 有 1-6 种方式可以选
cover_image 主题的背景图 cover.png 位于source\assets\images

改造

1. 添加 mermaid 支持

mermaid 是一款使用文本来绘制图表的工具,可以与 markdown 集成,使用标记语言完成流程图、序列图、甘特图等图表绘制。

tranquilpeak 主题不支持 mermaid 渲染,需要自己改造。

  1. 安装插件
    1
    npm install hexo-filter-mermaid-diagrams
  2. 修改配置文件:在 themes/tranquilpeak/_config.yml 中添加如下内容,表示启用 mermaid
    1
    2
    3
    4
    5
    6
    # Mermaid (markdwon to flow chart, seq chart, class chart ...)
    mermaid:
    enable: true
    version: 9.0.0
    # Available themes: default | dark | forest | neutral
    theme: default
  3. 修改 script.ejs 文件:在 themes/tranquilpeak/layout/_partial/script.ejs 末尾添加如下内容,完成 mermaid 初始化
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <% if (theme.mermaid.enable) { %>
    <script src='https://unpkg.com/mermaid@<%= theme.mermaid.version %>/dist/mermaid.min.js'></script>
    <script type="text/javascript">
    $(document).ready(function() {
    var mermaid_config = {
    startOnLoad: true,
    theme: '<%- theme.mermaid.theme %>'
    }
    mermaid.initialize(mermaid_config);
    });
    </script>
    <% } %>
  4. 修改_base.scss 文件:在 themes/tranquilpeak/source/_css/base/_base.scss 中,添加如下内容,设置 mermaid 图片样式,避免图片前后出现大片空白的情况。注意设置完后需要执行 npm run prod 重新构建主题,才能使得修改生效。
    1
    2
    3
    4
    pre.mermaid > svg {
    width: 100%;
    height: 100%;
    }

2. 添加目录导航侧边栏

对于长文浏览来说,目录导航能有效提高阅读体验。tranquilpeak 主题自带的 toc 不好用,生成的目录默认都位于文章最开头,对于长文不够友好。

tranquilpeak 主题支持多种屏幕大小,以及自定义的窗口样式。tocbot 作为外来者,适配窗口样式有点麻烦。我这个前端小白折腾了好久,终于让 tranquilpeak 勉强兼容了 tocbot,大致步骤如下:

  1. 安装 tocbot 插件:tocbot是一款自动根据标题构建目录的工具
    1
    npm install tocbot --save
  2. 修改配置文件:在 themes/tranquilpeak/_config.yml 中添加如下内容,表示启用 tocbot
    1
    2
    3
    4
    5
    6
    7
    8
    # add toc in post
    tocbot:
    enable: true
    tocSelector: '#post-toc'
    contentSelector: '.post-content'
    headings:
    - 'h2'
    - 'h3'
  3. 修改 script.ejs 文件:在 themes/tranquilpeak/layout/_partial/script.ejs 末尾添加如下内容,完成 tocbot 初始化
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <% if (theme.tocbot.enable) { %>
    <script src="https://cdn.jsdelivr.net/npm/tocbot@4.25.0/dist/tocbot.min.js"></script>
    <script type="text/javascript">
    tocbot.init({
    tocSelector: '<%- theme.tocbot.tocSelector %>', // 目录容器的 ID 或 class
    contentSelector: '<%- theme.tocbot.contentSelector %>', // 内容容器的 ID 或 class
    headingSelector: '<%- theme.tocbot.headings %>', // 包含在目录中的标题级别
    collapseDepth: 3,
    scrollSmooth: true,
    activeClass: 'active',
    orderedList: false
    });
    </script>
    <% } %>
  4. 修改 layout.ejs 文件:在 themes/tranquilpeak/layout/layout.ejs<%- body %>之前添加如下内容,在页面上添加 toc 空间
    1
    <%- partial('_partial/toc', {post: page}) %>
  5. 增加 toc.ejs 文件:在 themes/tranquilpeak/layout/_partial/ 目录下新建 toc.ejs 文件,实现对 toc 的样式控制
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    <% if (theme.tocbot.enable) { %>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tocbot/4.25.0/tocbot.css">
    <style>
    #post-toc {
    position: fixed !important;
    top: 80px;
    padding: 10px;
    z-index: 100;
    background-color: rgba(255,255,255,0);
    transform: translateX(0);
    right: 3%;
    width: 220px;
    height: auto;
    padding-top: 10px;
    padding-bottom: 10px;
    }
    </style>
    <script>
    var tocWidth = 220; // TOC 的固定宽度
    var tocPadding = 10; // TOC 的内边距,这里假设是两边各 10px,总和为 20px
    var tocRight = 0.03; // TOC 的右边框距离屏幕右边的距离相对屏幕宽度的占比

    // 检查窗口宽度并调整 TOC 显示
    function adjustToc() {
    var toc = document.getElementById('post-toc');
    var screenWidth = window.innerWidth || document.documentElement.clientWidth;
    var contentWrap = document.querySelector('div.post-content.markdown div.main-content-wrap');

    if (contentWrap) {
    var contentWidth = contentWrap.offsetWidth;
    // 计算 contentWrap 的宽度加上 TOC 的宽度和内边距
    var totalWidth = Math.round((contentWidth + tocWidth * 2 + tocPadding * 4) / (1 - tocRight * 2));

    if (totalWidth >= screenWidth) {
    toc.style.display = 'none'; // 如果总宽度大于或等于屏幕宽度,不显示 TOC
    } else {
    toc.style.display = 'block'; // 否则,显示 TOC
    }
    } else {
    toc.style.display = 'none'; // 如果无法获取 contentWrap 的宽度,不显示 TOC
    }
    }

    // 监听窗口大小变化事件
    window.addEventListener('resize', adjustToc);

    // 页面加载完毕时调用 adjustToc
    document.addEventListener('DOMContentLoaded', adjustToc);
    </script>
    <div id="post-toc" class="toc" style="display: none;"></div> <!-- 初始化时隐藏 -->
    <% } %>