自托管 GitHub Stats SVG:基于 Cloudflare Workers 的轻量级替代方案

66 阅读4分钟

最近在浏览 GitHub Profile README 时,发现自己主页的 github-readme-stats 用不了,anuraghazra/github-readme-stats 这个经典项目主要是用来展示个人统计卡片,比如 Stars、Forks、Followers 和 Top Languages。然而,这个项目的公共 Vercel 实例(github-readme-stats.vercel.app) 近年来经常出现不稳定情况——尤其是 2025 年底,有多个 Issue 报告显示卡片加载失败或显示错误

究其原因,主要还是 GitHub API 的速率限制问题。未经认证的请求每小时仅限 60 次,而公共实例被成千上万的用户共享,极易触发 403 Forbidden。即使项目本身实现了缓存,流量高峰期也难以完全避免中断。这让许多开发者在更新 Profile 时感到困扰:卡片时好时坏,影响了展示效果。

image.png

为什么需要自托管替代?

github-readme-stats 是一个优秀的开源项目,但依赖公共部署的痛点显而易见:

  • 共享限流:所有用户共用同一个 API 配额,热门时容易崩。
  • 不可控:无法自定义主题、缓存策略或添加个人化逻辑。
  • 隐私与性能:数据通过第三方服务中转,虽然开源但仍存在潜在风险。

自托管是更可靠的解决方案:你拥有独立的部署实例,使用自己的 GitHub Token(可选)来提升限额(从 60/h 提升到 5000/h),并通过缓存机制进一步优化。

Cloudflare Workers:完美的自托管平台

Cloudflare Workers 是边缘计算的理想选择:

  • 免费阶层充足:每天 10 万请求足够个人使用,甚至支持中等流量。
  • 全球边缘网络:响应延迟极低,SVG 加载几乎瞬间完成。
  • 内置 KV 支持:轻松实现数据缓存,无需额外数据库。
  • 零服务器运维:一键部署,无需管理 Node.js 环境或 Vercel 配额。

基于这些优势,我参考了社区的一些实现,整理了一个简洁、高效的 Cloudflare Worker 脚本。它功能聚焦于核心统计:Stars、Forks、Public Repos、Followers、Gists,以及 Top 5 Languages,并采用 Tokyonight 主题,确保视觉美观且垂直居中对齐完美。

源代码 Gist:gist.github.com/chenxuan520…

核心实现剖析

脚本的核心逻辑如下:

  1. 参数解析与基本防护

    • 通过 ?username=yourname 获取用户名。
    • 无参数时返回友好提示。
    • 拦截 favicon 请求,避免浏览器控制台错误。
  2. 缓存机制(KV)

    • 如果绑定了 STATS_CACHE KV Namespace,先查缓存(TTL 60 秒)。
    • 命中直接返回,添加 X-CF-Worker-Cache: HIT 调试头。
    • 未命中时异步写入缓存(使用 ctx.waitUntil 非阻塞)。
  3. GitHub API 调用

    • 支持可选 GITHUB_TOKEN 环境变量,提升限额。
    • 先获取用户基本信息(followers、public_repos 等)。
    • 再获取前 100 个仓库(per_page=100),计算 Stars/Forks。
    • 统计语言分布,取 Top 5 并计算百分比。
  4. SVG 生成优化

    • 使用 dominant-baseline: middle 实现完美垂直居中(避免传统 dy 偏移的字体兼容问题)。
    • XML 转义函数防止用户名特殊字符破坏 SVG。
    • 进度条使用渐变色数组,支持多种语言高亮。
    • 固定尺寸 495x195,圆角边框,Tokyonight 配色方案。
  5. 错误处理

    • 特别捕获 403 无 Token 情况,返回友好提示引导配置 Token。

相比原项目,这个实现更轻量(单文件、无外部依赖),聚焦于统计卡片而非多卡片支持,适合大多数 Profile README 需求。

部署步骤(只需 5 分钟)

  1. 创建 Worker

    • Cloudflare Dashboard → Workers & Pages → Create Worker。
    • 粘贴完整代码(见文末 Gist 链接),保存并部署。
  2. 可选配置(强烈推荐)

    • GITHUB_TOKEN:GitHub 生成一个无权限 Classic Token,添加到 Worker Variables。避免限流。
    • KV 缓存:创建 KV Namespace(如 github_stats),绑定变量名 STATS_CACHE
  3. 使用方式your-worker.your-subdomain.workers.dev/?username=y… 在 README 中嵌入:

    ![GitHub Stats](https://your-worker.workers.dev/?username=yourgithubname)
    

示例效果(以原作者 chenxuan520 为例):

screenshot-20251211-225224.png

进一步思考与扩展

  • 为什么选择 REST 而非 GraphQL?REST 更直观,且单次请求即可获取所需数据。GraphQL 虽强大,但对于简单统计 overhead 较大。
  • 缓存策略:60 秒 TTL 平衡了实时性和性能。如果你的仓库更新不频繁,可延长到 300 秒。
  • 自定义潜力:你可以轻松修改主题颜色、添加贡献热力图(需额外 API)、或支持暗黑/亮色切换。
  • 限流终极解决方案:结合 Token + KV,基本无忧。即使高流量,也远优于公共实例。

这个方案本质上是“个人化基础设施”的体现:在 Serverless 时代,我们不再依赖单一公共服务,而是通过几行代码构建属于自己的可靠工具。

源代码 Gist:gist.github.com/chenxuan520…

欢迎大家试用、Fork 并反馈。如果你在部署中遇到问题,评论区留言,我会尽力解答。让我们一起让 GitHub Profile 更稳定、更个性!