Waline评论系统部署与 Argon 极客页脚复刻
Hexo 博客折腾记:从零部署 Waline 到完美复刻 Argon 极客页脚
前言:
生命不息,折腾不止。为了给博客加上评论功能,我选择了 Waline。本以为是“一键部署”,结果踩了无数 Vercel 配置与 NPM 版本的坑。
搞定评论后,又顺手把 Butterfly 主题的页脚魔改成了 Argon 风格(显示服务器 IP、访客信息、精准运行时间)。
这是一篇保姆级避坑指南,记录了从后端搭建到前端 UI 深度魔改的全过程。
🛠 第一阶段:Waline 评论系统 —— 后端基石
Waline 的运行依赖于:LeanCloud (存储) + GitHub (托管) + Vercel (算力)。
1. 注册数据库 (LeanCloud)
- 访问 LeanCloud 官网(推荐使用国际版,免备案且稳定)。
- 创建应用:点击“创建应用”,建议起名为
blog-comment。 - 获取凭证:进入
应用 -> 设置 -> 应用凭证。
请务必记下:
App ID、App Key和Master Key。这是后续 Vercel 连接数据库的“钥匙”。
2. 构建代码仓库 (GitHub)
我们不使用一键部署,而是手动创建最纯净的代码结构,这能有效避免 Vercel 的路径识别报错。
- 在 GitHub 新建仓库
waline-server。 - 手动创建并提交以下三个核心文件:
package.json:锁定环境依赖。
{
"scripts": { "start": "waline" },
"dependencies": { "@waline/vercel": "latest" }
}
api/index.js:Serverless 函数入口。
⚠️ 避坑准则:入口文件必须放在
api文件夹内,否则 Vercel 无法将其识别为后端服务。
const { Waline } = require('@waline/vercel');
module.exports = Waline({ env: 'vercel' });
vercel.json:重定向逻辑。
⚠️ 避坑准则:没有它,访问域名会报 404 或直接暴露源码。
{
"version": 2,
"rewrites": [{ "source": "/(.*)", "destination": "/api/index.js" }]
}
3. 服务上线 (Vercel)
- 使用 GitHub 账号 登录 Vercel。
- Import Project:导入刚才创建的
waline-server。 - 配置环境变量:在
Environment Variables中填入:
LEAN_ID/LEAN_KEY/LEAN_MASTER_KEY
- 点击 Deploy。完成后你将获得一个
serverURL地址,建议绑定自己的子域名。
🎨 第二阶段:Butterfly 主题原生接入
服务端搞定后,回到 Hexo 修改 _config.butterfly.yml:
# 评论系统全局配置
comments:
use: Waline
count: true
# Waline 专属配置
waline:
serverURL: https://your-waline-url.vercel.app # 填入你的 Vercel 地址
pageview: true # 统计文章阅读量
# 安全设置:强制要求填写昵称和邮箱
meta: ['nick', 'mail']
requiredMeta: ['nick', 'mail']
🚀 第三阶段:复刻 Argon 硬核页脚 (深度魔改)
Butterfly 原生页脚略显单调,魔改版将实现:透明背景、全员居中、实时访客/服务器 IP 解析。
1. 结构重组:修改 Pug 模版
修改 themes/butterfly/layout/includes/footer.pug(操作前请务必备份)。
将原内容替换为以下“绝对居中版”结构:
//- 使用 Flex 布局实现绝对居中,背景透明适配各种主题色
#footer-wrap(style="background: transparent; color: #fff; text-align: center; padding: 20px 10px; display: flex; flex-direction: column; align-items: center; justify-content: center;")
.argon-footer(style="font-family: -apple-system, sans-serif; font-size: 14px; line-height: 1.8; width: 100%;")
//- 行1:服务器位置与运营商信息
#server-info(style="margin: 5px 0;")
| 现在为您提供服务的服务器是
span#cf-country 检测中...
|
img#cf-flag(src="https://raw.githubusercontent.com/hampusborgos/country-flags/main/svg/us.svg", alt="国旗", style="width: 16px; height: 16px; display:none; vertical-align: text-bottom; margin: 0 4px;")
| 城市:
span#cf-city ...
| ,IP:
span#cf-ip ...
| ,运营商:
span#cf-provider Hugging Face
//- 行2:访客地理位置解析
#user-info(style="margin: 5px 0;")
| 您来自
span#user-country 检测中...
|
img#user-flag(src="", alt="国旗", style="width: 16px; height: 16px; display:none; vertical-align: text-bottom; margin: 0 4px;")
| 城市:
span#user-city ...
| ,IP:
span#user-ip ...
| ,运营商:
span#user-org ...
//- 行3:精准稳定运行时间
.time-container(style="margin: 5px 0;")
| 本博客已稳定运行
span#timeid1.time-element(style="color: #ffd700; font-weight: bold; margin: 0 3px;") 0
| 天
span#timeid2.time-element(style="color: #ffd700; font-weight: bold; margin: 0 3px;") 0
| 小时
span#timeid3.time-element(style="color: #ffd700; font-weight: bold; margin: 0 3px;") 0
| 分
span#timeid4.time-element(style="color: #ffd700; font-weight: bold; margin: 0 3px;") 0
| 秒
//- 行4:致敬 Butterfly
div(style="margin-top: 5px;")
| Theme
a(href="https://butterfly.js.org/", target="_blank", style="font-weight:bold; color: #fff; text-decoration: none; border-bottom: 1px dashed rgba(255,255,255,0.5);") Butterfly
2. 注入灵魂:增强版 JS 逻辑
新建或修改 source/js/custom.js。
技术亮点:
阿里云 DoH:替换被墙的 Google DNS,确保国内直连访客数据不报错。
IP 数字净化:针对 CloudFront 等 CDN 返回的别名网址,正则提取真实数字 IP。
PJAX 适配:监听
pjax:complete,确保切换页面时页脚数据不消失。
/* source/js/custom.js */
function runArgonWidget() {
// 1. 动态计时器
const boomDate = new Date("2026/01/01 00:00:00"); // 👈 改为你自己的建站时间
function updateTime() {
try {
const now = new Date();
const diff = now - boomDate;
if (diff < 0) return;
document.getElementById("timeid1").innerText = Math.floor(diff / 86400000);
document.getElementById("timeid2").innerText = Math.floor((diff % 86400000) / 3600000);
document.getElementById("timeid3").innerText = Math.floor((diff % 3600000) / 60000);
document.getElementById("timeid4").innerText = Math.floor((diff % 60000) / 1000);
} catch (err) {}
}
if (window.argonInterval) clearInterval(window.argonInterval);
window.argonInterval = setInterval(updateTime, 1000);
updateTime();
// 2. 访客 IP 地理位置
const userCountry = document.getElementById('user-country');
if (userCountry) {
userCountry.innerText = "查询中...";
fetch('https://ipapi.co/json/')
.then(res => res.json())
.then(data => {
userCountry.innerText = data.country_name || "未知";
document.getElementById('user-city').innerText = data.city || "...";
document.getElementById('user-ip').innerText = data.ip || "...";
document.getElementById('user-org').innerText = data.org || "运营商";
const flag = document.getElementById('user-flag');
if (data.country_code) {
flag.src = `https://raw.githubusercontent.com/hampusborgos/country-flags/main/svg/${data.country_code.toLowerCase()}.svg`;
flag.style.display = 'inline';
}
}).catch(() => { userCountry.innerText = "网络异常"; });
}
// 3. 服务器 IP (阿里云 DNS 解析版)
const cfCountry = document.getElementById('cf-country');
if (cfCountry && window.location.hostname !== 'localhost') {
cfCountry.innerText = "解析中...";
fetch(`https://dns.alidns.com/resolve?name=${window.location.hostname}&type=1`)
.then(res => res.json())
.then(data => {
if (data.Answer) {
const ipRecord = data.Answer.find(ans => ans.type === 1);
document.getElementById('cf-ip').innerText = ipRecord ? ipRecord.data : data.Answer[0].data;
cfCountry.innerText = "Global CDN";
document.getElementById('cf-flag').style.display = 'inline';
}
});
}
}
// 初始化运行
runArgonWidget();
// 兼容 PJAX 切换
document.addEventListener('pjax:complete', runArgonWidget);
第四阶段:激活脚本 —— 引入 custom.js
代码写完并不代表它会自动运行。Butterfly 主题需要通过配置文件手动“点火”,才能在浏览器中加载并执行你的自定义逻辑。
1. 修改主题配置文件
打开博客根目录下的 _config.butterfly.yml,搜索 inject 配置项。
2. 添加引用代码
在 bottom(即页面底部,</body> 标签之前)添加你的脚本路径。请确保这里的路径与你在 source 文件夹下存放的文件路径一致。
# Inject the logic to your site
inject:
head:
# 这里可以放一些需要在头部加载的 CSS
bottom:
# 引用复刻 Argon 页脚的灵魂脚本
- <script src="/js/custom.js"></script>
3. 强制刷新与生效
⚠️ 避坑准则:Hexo 的缓存非常顽固,修改完 JS 后必须执行“三连”操作,否则浏览器可能还在运行旧的代码。
在终端执行:
hexo clean && hexo g && hexo s
然后在浏览器中按下 Ctrl + F5(Windows)或 Cmd + Shift + R(Mac)进行强制刷新。
📝 避坑终极避坑总结
- 缓存是大敌:修改完配置务必执行
hexo clean,否则你看到的永远是旧样式。 - DNS 策略:国内环境下必须使用阿里云/腾讯云的 DNS 接口,使用 Google DNS 会导致直连访客看到“DNS 错误”。
- 玄学位置:若开启了 iCloud 专用代理 或 梯子,访客 IP 会显示为美国/日本,这是物理层面的代理转发,属正常现象。
结语:Hexo 的魅力就在于折腾。当看到页脚的跳动秒数与精准的服务器信息交织在一起时,这一天的汗水都化成了满满的成就感。
Would you like me to help you further with specific CSS styling for the footer elements?