最近给自己的 GitHub Pages 个人主页做了一次升级。最纠结的一个问题是:要不要迁移到更现代的框架(Astro)? 最终我选择了「在现有 Jekyll 基础上做增量改造」。这篇文章聊聊为什么,以及各项功能是怎么落地的。
一、先看清现状,别急着动手
很多人拿到一个老项目,第一反应是”重写”。但在动手前,我花了半小时把仓库彻底摸了一遍,发现它的真实形态和”老旧”的印象并不完全一样:
- 框架是 Jekyll(Hux/BY Blog 主题 fork),GitHub Pages 对
master分支自动构建,不需要任何 CI。 - 首页是一个纯静态自定义页(约 1100 行),暖色调编辑风 + 中英双语切换 + PWA,手工打磨的痕迹很重。
- 文章只有 2 篇,而且全站居然没有博客列表页——首页博客区只是外链到 CSDN。
- 评论系统 Gitalk 的
clientSecret明文躺在_config.yml里(公开仓库的严重安全隐患)。 - SEO 几乎为零:没有 OG 标签、没有 sitemap、没有结构化数据。
这个”体检”直接改变了我对方案的判断。
二、核心决策:为什么不迁移 Astro
朋友给的计划书建议全量迁移到 Astro(SSG、零 JS、Content Collections、Pagefind……听起来很美好)。我一度也动心,但冷静分析后否决了:
1. 迁移成本与风险不成正比 首页是 1100 行手工定制设计,还带 PWA 和双语逻辑。全量迁移 = 把这套设计用 Astro 组件重写一遍,样式还原、交互还原,风险极高——很可能把用户精心打磨的视觉效果改坏。
2. 功能上 Jekyll 完全够用 分类、标签、归档、RSS、sitemap,这些都是 Jekyll 原生或 GitHub Pages 白名单插件自带的能力。博客内容只有 2 篇,不存在性能或内容规模问题。
3. 部署链路零改动 GitHub Pages 原生构建 Jekyll,push 即上线。迁移 Astro 反而要引入 GitHub Actions + 改部署分支,徒增复杂度。
结论:框架迁移的本质动机应该是”现有技术栈无法满足需求”,而不是”新框架更酷”。 这次需求全部能用增量实现,于是选择了零风险的路线。
三、增量改造的落地清单
最终方案:保留 Jekyll + 现有首页设计,叠加全部新功能。逐项看怎么做的。
1. 文章系统:分类、标签、搜索
- 新增
/blog/列表页(文章卡片:标题、日期、摘要、分类、标签)。 - 新增
/categories/分类归档页;/tags/标签页保留。 - 文章 frontmatter 增加
categories与description字段,Jekyll 自动聚合。
搜索用的是 Fuse.js(轻量模糊搜索库,本地化部署无后端)。核心思路是让 Jekyll 在构建时生成一份 search.json 索引(标题/正文/摘要/分类/标签),前端 Fuse.js 加载后即时模糊搜索,完全离线、零依赖:
// search.json —— Jekyll 构建时自动生成
{
"title": "文章标题",
"url": "/blog/my-post/",
"date": "2026-09-02",
"content": "正文全文…",
"categories": ["技术"],
"tags": ["Jekyll"]
}
// 前端 Fuse.js 全文搜索
const fuse = new Fuse(data, {
keys: [
{ name: 'title', weight: 0.4 },
{ name: 'content', weight: 0.3 },
{ name: 'tags', weight: 0.1 },
{ name: 'categories', weight: 0.05 }
],
threshold: 0.4,
ignoreLocation: true
});
新文章自动进入搜索/分类/sitemap/RSS——因为索引都是构建时生成的,写 Markdown 推上去就行,工作流完全不变。
踩坑:加上
categories后,Jekyll 默认 permalink 会把中文分类名 URL 编码进路径(/%E6%8A%80%E6%9C%AF/...),等于改了所有旧文章链接,会破坏已收录的 SEO。解决:显式设permalink: /blog/:title/,语义化且与分类解耦,链接永久稳定。
2. 评论系统:Gitalk → Giscus
原 Gitalk 需要把 clientSecret 暴露在前端,密钥明文躺在公开仓库里,这是必须处理的隐患。
换成 Giscus(基于 GitHub Discussions):
- 无任何密钥暴露,更安全
- 免费、无广告、支持 GitHub 登录
- 支持 Markdown、表情回应、跟随系统主题
- 评论数据直接落在仓库的 Discussions 里
接入就是一段 <script>(repo-id / category-id 从 giscus.app 获取):
<script src="https://giscus.app/client.js"
data-repo="owner/repo"
data-repo-id="你的repo-id"
data-category="Announcements"
data-category-id="你的category-id"
data-mapping="pathname"
data-theme="preferred_color_scheme"
data-lang="zh-CN"
crossorigin="anonymous" async></script>
3. SEO:Meta / OG / Twitter / JSON-LD / Sitemap
Jekyll 页面统一在 _includes/head.html 用 Liquid 动态生成:每个页面独有的 Title、Description、Keywords,加上 Open Graph、Twitter Card、canonical,以及 JSON-LD 结构化数据(文章页 BlogPosting,其他页 WebSite + Person):
<meta property="og:title" content="{{ page.title }} - {{ site.SEOTitle }}">
<meta property="og:url" content="{{ page.url | prepend: site.url }}">
<meta property="og:image" content="{{ site.url }}/img/profile.jpg">
<meta name="twitter:card" content="summary_large_image">
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BlogPosting",
"headline": "…",
"datePublished": "…",
"author": { "@type": "Person", "name": "…" }
}
</script>
Sitemap & robots:GitHub Pages 白名单里有 jekyll-sitemap,加一行配置自动生成 sitemap.xml;再手写 robots.txt 引用它。
特别提醒:如果首页是不走 Jekyll 模板的纯静态文件,那
head.html对它不生效,需要在首页<head>里单独手写一遍 SEO 标签。这是最容易漏的点。
4. 流量统计 GA4
统一在 head.html 注入 gtag.js,Measurement ID 放 _config.yml 配置(好管理):
<script async src="https://www.googletagmanager.com/gtag/js?id={{ site.ga4_track_id }}"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '{{ site.ga4_track_id }}');
</script>
静态首页同样单独加一份。替换真实 ID 后即可在 GA 后台看到访问数据。
5. 打赏:GitHub Sponsors
配置一个链接 https://github.com/sponsors/kjlintong,在页脚、文章页底部、首页都放了入口按钮。别人点击即可通过 GitHub Sponsors 打赏,无手续费、纯官方渠道。
更新(2026-09-14):打赏通道已切换为 Ko-fi,页脚、文章页底部、首页入口均已同步更新。
6. 首页文章区:让 Jekyll 渲染最新文章
原本首页只是两个外链卡片。用户希望像”精选项目”一样展示文章列表。关键技巧:给原本纯静态的 index.html 加一个空 frontmatter(---),Jekyll 就会用 Liquid 渲染它,文章列表随之自动更新:
---
---
{% for post in site.posts limit:3 %}
<!-- 文章卡片:标题 / 日期 / 摘要 / 分类 / 标签 -->
{% endfor %}
前置检查:确认首页里没有 Liquid 模板语法残留(左花括号加左花括号、或左花括号加百分号这类组合),才敢加 frontmatter。改造后要重新验证 JS 和双语逻辑没被破坏。
四、值得记住的经验
- 先体检,再决策。动手前摸清仓库真实结构,避免基于错误假设做方案。
- 增量优于重写。框架迁移的成本经常被低估(重写设计、改部署、回归测试),收益常被高估。需求能用现有栈实现,就别折腾。
- 公开仓库禁止放任何密钥。Gitalk 的 clientSecret 明文在仓库里 = 裸奔,务必换掉(Giscus 无密钥暴露)。
- 改 URL 结构要谨慎。中文分类名进 permalink 会悄悄改变所有旧链接,破坏 SEO——用稳定的自定义 permalink。
- 静态首页容易漏 SEO。不走模板的纯静态页面,
head.html不生效,要单独补一遍 OG/JSON-LD/GA4。
五、结语
这次升级没有换框架、没有重写首页,却在保留原有视觉设计的前提下,补齐了文章系统、全文搜索、评论、SEO、统计、打赏这些现代站点标配。有时候最好的重构,就是清醒地决定”不重构”。 希望这次的取舍思路和落地细节,对同样维护着老博客的你有所帮助。
如果你也在折腾 Jekyll / GitHub Pages 站点,欢迎在评论区交流,或者通过 Ko-fi 请我喝杯咖啡 ☕
-
Previous
个人主页升级实战:Jekyll 增量改造的取舍与落地Upgrading My Personal Site: Jekyll Incremental Refactoring — Trade-offs and What Actually Shipped -
Next
用 5 行代码预测模型瓶颈:MLSys·im Roofline 教程学习笔记Predicting Model Bottlenecks in 5 Lines of Code: MLSys·im Roofline Tutorial Notes
If this post helped you, a coffee is always welcome ☕