博客搭建小记
Hexo + Fluid 博客搭建与配置记录
本文记录了个人博客的搭建与配置过程,主要涵盖 Hexo 基础配置、Nord 风格配色修改、自定义功能代码注入,以及 Obsidian 写作工作流的接入。特别记录了在增加自定义功能时,本地测试与线上部署的差异及解决方案。
1. 博客搭建与写作工作流配置
博客的核心框架使用 Hexo,采用 Fluid 主题,日常写作与发布通过 Obsidian 软件完成。
- Hexo 与主题安装:
- 在本地环境中安装 Node.js 与 Git。
- 通过终端执行
npm install -g hexo-cli安装 Hexo,初始化博客文件夹并安装相关依赖。 - 下载 Fluid 主题文件,在博客根目录的主配置文件
_config.yml中,将theme字段修改为fluid。
- 接入 Obsidian 工作流:
- 将原有 Obsidian 笔记库的
.obsidian配置文件夹复制到 Hexo 的根目录,以保留常用的快捷键和插件设置。 - 在 Obsidian 中安装并启用
Shell commands插件。配置以下终端命令用于自动化上传:1
git add . && git commit -m "update post" && git push origin main - 使用
Commander插件,将上述命令绑定至操作界面的侧边栏图标。
- 将原有 Obsidian 笔记库的
- 部署上线:
将本地代码推送到 GitHub 仓库。在 Vercel 平台导入该仓库并开启自动构建。完成文章撰写后,点击 Obsidian 中的执行图标,即可触发自动推送与 Vercel 的线上部署。
2. 视觉风格与 Nord 配色修改
博客的整体视觉参考 Nord 配色风格。该风格主要使用低饱和度的冷色调,以灰白、深灰蓝作为背景与文本的基础色,并使用淡蓝色作为强调色。
- 基础颜色修改:
打开_config.fluid.yml文件,定位至color配置项。修改背景色与超链接颜色如下:1
2
3
4
5
6
7color:
body_bg_color: "#ECEFF4"
body_bg_color_dark: "#2E3440"
board_color: "#FFFFFF"
board_color_dark: "#3B4252"
post_link_color: "#81A1C1"
link_hover_color: "#5E81AC" - 细节样式修改:
- 在
source/css/目录下新建custom.css文件。 - 在
_config.fluid.yml中配置引入该文件:1
2custom_css:
- /css/custom.css - 在
custom.css中写入 CSS 代码,统一组件的 Nord 风格样式。例如:1
2
3
4
5/* 引用块边框与背景 */
.markdown-rendered blockquote {
border-left: 4px solid #81A1C1 !important;
background-color: rgba(129, 161, 193, 0.1);
}
- 在
3. 动态注入分享与赞赏功能(避坑指南)
由于当前版本的 Fluid 主题未在配置文件中提供底层的分享与赞赏模板支持,需要自行增加页面元素。在此过程中,我遇到了经典的“本地与线上部署差异”陷阱。
踩坑记录:node_modules 陷阱与 Vercel 延迟
最初尝试直接修改 node_modules/hexo-theme-fluid/layout/post.ejs 源码。该方案在本地(localhost)测试完美生效,但推送至 Vercel 网页版后却毫无变化。
原因在于:Git 默认会忽略 node_modules 文件夹。推送至 GitHub 的代码并不包含修改后的主题源码,Vercel 在云端构建时会重新拉取一份纯净的默认主题。
此外,在 Vercel 部署完成后,云端 CDN 缓存和文件生成存在短暂延迟,刚上线时访问新加入的静态资源可能会遇到 404 (Not Found) 报错,通常等待 1-2 分钟并强制刷新即可解决。
最终方案:前端 DOM 动态注入
为了不破坏主题的纯净性(便于后续升级),最终采用 JavaScript 动态注入的方法,避开源码修改。
编写注入脚本:
在source/js/目录下新建custom.js,写入以下代码,通过 DOM 操作将 HTML 骨架插入文章末尾: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
34document.addEventListener('DOMContentLoaded', function() {
var articleBody = document.querySelector('.markdown-body');
if (!articleBody) return; // 仅在文章页执行
var injectHTML = `
<div class="post-reward-share" style="text-align: center; margin-top: 40px;">
<div class="reward-container">
<button id="reward-btn" style="color: #81A1C1; border: 1px solid #81A1C1; background: transparent; padding: 5px 15px; border-radius: 5px; cursor: pointer;">赞赏支持</button>
<div id="reward-qr" style="display: none; margin-top: 15px;">
<img src="/img/wechat.png" alt="微信打赏" style="width: 150px; margin: 0 10px;">
<img src="/img/alipay.png" alt="支付宝打赏" style="width: 150px; margin: 0 10px;">
</div>
</div>
<div class="social-share" data-sites="wechat,weibo,qq,twitter" style="margin-top: 20px;"></div>
</div>
`;
articleBody.insertAdjacentHTML('afterend', injectHTML);
// 绑定点击事件
document.getElementById('reward-btn').onclick = function() {
var qr = document.getElementById('reward-qr');
qr.style.display = qr.style.display === 'none' ? 'block' : 'none';
};
// 加载 Share.js 资源
var shareCSS = document.createElement('link');
shareCSS.rel = 'stylesheet';
shareCSS.href = '[https://lib.baomitu.com/social-share.js/1.0.16/css/share.min.css](https://lib.baomitu.com/social-share.js/1.0.16/css/share.min.css)';
document.head.appendChild(shareCSS);
var shareJS = document.createElement('script');
shareJS.src = '[https://lib.baomitu.com/social-share.js/1.0.16/js/social-share.min.js](https://lib.baomitu.com/social-share.js/1.0.16/js/social-share.min.js)';
document.body.appendChild(shareJS);
});配置脚本引入:
在_config.fluid.yml中注册该 JS 文件,Hexo 编译时会将其合法推送到云端:1
2custom_js:
- /js/custom.js
4. 域名绑定与网站收录
完成本地功能开发后,将博客绑定至独立域名并提交至搜索引擎。
- 域名解析:
在 Vercel 平台添加自定义域名,获取平台分配的 CNAME 记录值或 IP 地址。前往域名注册商的 DNS 控制台,添加对应的 A 记录(指向@)和 CNAME 记录(指向www)。 - 修改主链接:
在博客主配置文件_config.yml中,修改url字段:1
url: [https://rlidac.top](https://rlidac.top) - 生成站点地图:
在终端运行npm install hexo-generator-sitemap --save。随后在_config.fluid.yml中将canonical设为true。 - 向 Google 提交收录:
重新部署后,网站根目录将生成sitemap.xml文件。登录 Google Search Console 添加 TXT 记录验证域名所有权。验证完成后,在后台的“站点地图”页面提交sitemap.xml路径,等待搜索引擎爬虫抓取。