Skip to content

Repository files navigation

🚀 GitHub Analyzer

一个基于 Next.js + TypeScript 构建的生产级 GitHub 技术栈画像分析工具
区别于市面上盲目累加代码量的统计工具,内置智能交集过滤算法,真实还原开发者的核心技术栈。

Next.js React TypeScript License

🌐 Live Demo · 📖 API 文档 · 🛠️ 部署指南


✨ 核心亮点

🧠 智能交集统计算法 (Core Engine)

项目的核心优势——保守交集策略,完美剔除开源大项目带来的"数据杂音":

  • 自有仓库:全量信任,精准累加所有语言字节数
  • 贡献仓库:采用保守交集策略,仅在开发者自有项目已拥有的语言上累加贡献量
    • 例如:你偶然改动某个大型开源项目的一行配置引入了整个 Shell/NPM 环境,不会被计入统计
    • 效果:得到的是核心技术栈,而非"历史垃圾"的集合

🛡️ 工业级安全防护

✓ GraphQL 变量参数化协议 (杜绝注入)
✓ 严格的 GitHub 账号规范正则验证
✓ 完整的 CORS 预检支持
✓ 类型安全的 TypeScript 接口

⚡ 高可用 SRE 级优化

✓ 指数退避重试机制 (1s → 2s → 4s)
✓ 智能 Retry-After 头解析
✓ 15 秒硬超时熔断
✓ 标准 OPTIONS 预检请求支持

🎨 开箱即用的可视化

✓ 响应式 Conic Gradient 饼图
✓ 语言颜色方案同 GitHub 官方
✓ 支持 Iframe 跨域嵌入
✓ 实时冷却计数器防止 API 滥用

🛠️ 技术栈

工具 版本 说明
Next.js 16.2.6 App Router + Route Handlers
React 19.2.4 最新 React Hooks
TypeScript 5 完整类型覆盖
Tailwind CSS 4 原子化样式
GraphQL - GitHub API v4

🚀 快速开始

前置要求

  • Node.js 18+
  • npm / pnpm / yarn / bun
  • GitHub 个人访问令牌 (PAT)

1️⃣ 克隆仓库

git clone https://github.com/Linvin-1233/GitHub-Analyzer.git
cd GitHub-Analyzer

2️⃣ 生成 GitHub Token

前往 GitHub 设置 → Developer settings → Personal access tokens

权限需求(最小化原则):

  • public_repo — 读取公开仓库信息
  • ✗ 无需写入权限

复制 Token,保存到本地。

3️⃣ 配置环境变量

在项目根目录创建 .env.local 文件:

# .env.local
GITHUB_TOKEN=ghp_your_actual_github_token_here
NEXT_PUBLIC_APP_URL=http://localhost:3000

生产环境提示:在 Vercel / 服务器部署时,需在对应平台的环境变量配置中设置上述两个变量。

4️⃣ 安装依赖 & 启动开发服务器

npm install
npm run dev

访问 http://localhost:3000,看到熟悉的 GitHub Stats 界面即成功!


📖 API 文档

获取用户技术栈统计

请求

GET /api/github-stats?username=octocat HTTP/1.1
Host: your-domain.vercel.app
Content-Type: application/json

请求参数

参数 类型 必填 描述 示例
username string GitHub 用户名(1-39 位,英文字母、数字、连字符) octocat

成功响应 (200 OK)

{
  "my_username": "octocat",
  "scope": "GitHub-Analyzer-V1.12",
  "summary": {
    "total_repositories_analyzed": 12,
    "total_code_bytes": 1458920
  },
  "languages_percentage": {
    "TypeScript": "65.4%",
    "JavaScript": "20.1%",
    "CSS": "14.5%"
  },
  "languages_by_bytes": {
    "TypeScript": 954134,
    "JavaScript": 293243,
    "CSS": 211543
  },
  "repositories": [
    "octocat/hello-world",
    "octocat/spoon-knife"
  ]
}

响应头示例

Cache-Control: public, max-age=600
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, OPTIONS
Content-Type: application/json

错误响应

状态码 错误信息 原因
400 Invalid username 用户名为空或格式非法
404 User not found GitHub 中不存在该用户
500 Missing GITHUB_TOKEN 服务端未配置环境变量
502/503 GitHub API error GitHub 服务暂时不可用(会自动重试)

🎯 使用示例

场景 1:在你的 README 中展示技术栈

## 📊 我的技术栈

<iframe src="https://github-analyzer-six-theta.vercel.app/?username=YOUR_USERNAME&embed=true" 
        width="100%" height="520" frameborder="0">
</iframe>

场景 2:在你的网站中调用 API

const username = 'octocat';
const response = await fetch(`/api/github-stats?username=${username}`);
const data = await response.json();

console.log(`${username} 的核心语言:${Object.keys(data.languages_percentage)[0]}`);
console.log(`统计的仓库数:${data.summary.total_repositories_analyzed}`);

场景 3:跨域 CORS 调用

<!-- 从任意网站都可以调用 -->
<script>
fetch('https://github-analyzer-six-theta.vercel.app/api/github-stats?username=octocat')
  .then(res => res.json())
  .then(data => console.log(data))
  .catch(err => console.error(err));
</script>

🏗️ 项目结构

GitHub-Analyzer/
├── app/
│   ├── api/
│   │   ├── github-stats/
│   │   │   └── route.ts          # 核心 API 路由
│   │   └── embed/
│   │       └── route.ts          # Iframe 嵌入支持
│   ├── components/
│   │   └── GitHubStatsViewer.tsx  # 前端可视化组件
│   ├── globals.css                # 全局样式 (Tailwind)
│   ├── layout.tsx                 # 根布局
│   └── page.tsx                   # 首页
├── public/
│   └── data/
│       └── colors.json            # GitHub 语言颜色方案
├── package.json                   # 依赖配置
├── tsconfig.json                  # TypeScript 配置
├── tailwind.config.js             # Tailwind 配置
├── next.config.js                 # Next.js 配置
├── .env.local                     # 本地环境变量 (Git 忽略)
└── README.md                      # 本文件

🔧 核心代码解析

API 层的智能交集算法 (app/api/github-stats/route.ts)

// 自有仓库:100% 累加
if (isOwned) {
    repoSet.add(repo.nameWithOwner);
    for (const edge of repo.languages.edges) {
        const lang = edge.node.name;
        languageStats[lang] = (languageStats[lang] || 0) + edge.size;
    }
    continue;
}

// 贡献仓库:保守交集策略
if (isContributed) {
    repoSet.add(repo.nameWithOwner);
    for (const edge of repo.languages.edges) {
        const lang = edge.node.name;
        if (!languageStats[lang]) continue;  // 只计算已有的语言
        languageStats[lang] += edge.size;
    }
}

前端响应式设计 (app/components/GitHubStatsViewer.tsx)

// Conic Gradient 饼图
<div
    className="w-56 h-56 rounded-full shadow-lg transition-transform hover:scale-105"
    style={{ background: `conic-gradient(${gradientParts.join(', ')})` }}
/>

// 语言颜色方案同 GitHub 官方
const color = githubColors[lang]?.color || '#8b5cf6';

🚀 部署指南

方案 1:Vercel(推荐,5 分钟)

  1. Fork 本仓库 到你的 GitHub 账号
  2. 访问 vercel.com → 选择该 Fork 仓库
  3. Environment Variables 中添加:
    GITHUB_TOKEN = ghp_xxx...
  4. 点击 Deploy → 1-2 分钟后自动上线!

优势

  • ✓ 自动 CI/CD(Git Push 自动部署)
  • ✓ 全球 CDN 加速
  • ✓ 无需管理服务器
  • ✓ 免费额度充足

方案 2:自托管 (Node.js Server)

# 构建生产版本
npm run build

# 启动服务器
npm start

# 或使用 PM2 后台运行
npm install -g pm2
pm2 start npm --name "github-analyzer" -- start
pm2 save
pm2 startup

需要在 Nginx / Apache 中配置反向代理。

方案 3:Docker 容器部署

FROM node:18-alpine

WORKDIR /app

COPY package*.json ./
RUN npm install

COPY . .
RUN npm run build

ENV GITHUB_TOKEN=${GITHUB_TOKEN}
ENV NEXT_PUBLIC_APP_URL=${NEXT_PUBLIC_APP_URL}

EXPOSE 3000

CMD ["npm", "start"]
# 构建镜像
docker build -t github-analyzer .

# 运行容器
docker run -e GITHUB_TOKEN=ghp_xxx \
           -e NEXT_PUBLIC_APP_URL=https://your-domain \
           -p 3000:3000 \
           github-analyzer

📊 API 限流和缓存策略

GitHub API 速率限制

  • 已认证请求:5000 requests/hour
  • 重试机制:自动 3 次指数退避重试
  • 超时设置:单次请求 15 秒硬超时

我们的缓存策略

浏览器缓存 (Cache-Control)
    ↓
600秒 (10分钟) 边缘缓存
    ↓
Vercel Edge Network (全球 CDN)

这意味着同一用户的查询在 10 分钟内只会真实请求 GitHub API 一次,其余都是秒级响应!


🐛 生产排查日志

服务端运行时的关键日志(console.log):

[GitHub-Stats] Cache MISS. Initiating fresh analysis...
[GitHub-Stats] Retry attempt 1 for octocat...
[GitHub-Stats] Retry attempt 2 for octocat... (网络抖动中)
[GitHub-Stats] Cache HIT for octocat (毫秒级响应)
[GitHub-Stats] Request DEDUPLICATED for octocat (高并发时)

❓ 常见问题

Q1: GitHub Token 在哪里生成?

👉 GitHub Settings → Developer settings → Personal access tokens

权限只需勾选 public_repo

Q2: 为什么某些用户的查询会失败?

可能的原因

  1. 用户没有公开仓库
  2. GitHub API 触发频率限制(每小时 5000 请求)
  3. Token 权限不足
  4. 用户名包含特殊字符(仅支持英文字母、数字、连字符)

Q3: 为什么贡献仓库中的某些语言没被统计?

这是设计中的保守交集策略。如果你想包含所有贡献的语言,可以修改 app/api/github-stats/route.ts 中的这行:

// 修改前:仅计算已有语言
if (!languageStats[lang]) continue;

// 修改后:计算所有语言
// if (!languageStats[lang]) languageStats[lang] = 0;

Q4: 如何修改缓存时间?

app/api/github-stats/route.ts 中找到:

"Cache-Control": "public, max-age=600",  // 600 = 10 分钟

改为 max-age=3600 (1 小时) 或其他值。

Q5: 单个请求的超时时间是多少?

硬超时15 秒。在 app/api/github-stats/route.ts 中:

const timeoutId = setTimeout(() => controller.abort(), 15000);  // 毫秒

Q6: 可以在 Vercel 之外部署吗?

可以。项目是标准的 Node.js Next.js 应用,支持任何支持 Node.js 的平台:

  • Heroku / Railway / Render(PaaS)
  • AWS / GCP / Azure(IaaS)
  • 你自己的 VPS

🤝 贡献指南

欢迎提交 Issue 和 PR!

改进方向

  • 支持更多数据维度(如按时间范围统计)
  • 国际化多语言
  • 单元测试覆盖

提交 PR 时,请

  1. Fork 本仓库
  2. main 新建 feature 分支
  3. 提交清晰的 commit 消息
  4. 确保代码通过 TypeScript 检查
  5. 在 PR 中说明改动原因

📄 开源许可

本项目基于 MIT License 开源,详见 LICENSE 文件。


📚 参考资源


🙏 致谢

感谢所有使用、Star 和贡献的开发者!


Releases

Packages

Contributors

Languages