Skip to content

Next.js 页脚集成 Wakatime 统计 (Cloudflare Worker API)

本教程将指导您完成一个实用的功能:在您的 Next.js 应用的页脚动态显示来自 Wakatime 的编程时长统计。为了安全地管理您的 Wakatime API Key,我们将使用 Cloudflare Workers 作为中间 API 服务。

学习目标

  • 创建一个 Cloudflare Worker 来代理 Wakatime API 请求。
  • 在 Cloudflare Worker 中安全地存储和使用 Wakatime API Key。
  • 在 Next.js 组件中调用 Cloudflare Worker API。
  • 在应用页脚展示获取到的 Wakatime 数据。

前提条件

  • 拥有一个 Wakatime 账户及对应的 API Key。
  • 拥有一个 Cloudflare 账户。
  • 熟悉 Next.js 和 React 的基础知识。
  • Node.js 和 npm/yarn 已安装。
  • 推荐安装 Cloudflare 的 wrangler CLI 工具 (可选,也可以通过 Cloudflare Dashboard 操作)。

步骤概览

  1. 创建 Cloudflare Worker 项目
  2. 编写 Worker 逻辑以获取 Wakatime 数据
  3. 配置并部署 Cloudflare Worker
  4. 在 Next.js 中创建或修改 Footer 组件
  5. 在 Footer 组件中调用 Worker API 并显示数据

步骤 1: 创建 Cloudflare Worker 项目

您可以通过 Cloudflare Dashboard 或使用 wrangler CLI 来创建 Worker。

使用 Wrangler CLI (推荐):

Terminal window
# 安装 wrangler (如果尚未安装)
npm install -g wrangler
# 登录 wrangler
wrangler login
# 创建新的 Worker 项目
wrangler init my-wakatime-worker
cd my-wakatime-worker

这会创建一个包含 wrangler.toml (配置文件) 和 src/index.js (或 index.ts,Worker 代码) 的项目。

通过 Cloudflare Dashboard:

  1. 登录 Cloudflare Dashboard。
  2. 导航到 “Workers & Pages”。
  3. 点击 “Create application”,然后选择 “Create Worker”。
  4. 给您的 Worker 一个唯一的名称 (例如 wakatime-api-proxy),然后点击 “Deploy”。
  5. 点击 “Edit code” 进入在线编辑器。

步骤 2: 编写 Worker 逻辑以获取 Wakatime 数据

打开 src/index.js (或您在 Dashboard 中编辑的文件),并替换为以下内容:

export default {
async fetch(request, env, ctx) {
// 允许所有来源的 CORS 请求 (在生产环境中您可能希望更严格)
const corsHeaders = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, HEAD, POST, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type',
};
// 处理 OPTIONS 预检请求
if (request.method === 'OPTIONS') {
return new Response(null, { headers: corsHeaders });
}
// 从环境变量中获取 Wakatime API Key
const WAKATIME_API_KEY = env.WAKATIME_API_KEY;
if (!WAKATIME_API_KEY) {
return new Response(
JSON.stringify({ error: 'Wakatime API key not configured in Worker environment' }),
{
status: 500,
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
}
);
}
// Wakatime API URL
// 您可以根据需要调整 range 参数, e.g., last_7_days, last_30_days, last_6_months, last_year
const wakatimeUrl = `https://wakatime.com/api/v1/users/current/all_time_since_today?api_key=${WAKATIME_API_KEY}`;
try {
const response = await fetch(wakatimeUrl);
if (!response.ok) {
const errorText = await response.text();
console.error(`Wakatime API error: ${response.status} ${errorText}`);
return new Response(
JSON.stringify({ error: 'Failed to fetch data from Wakatime API', details: errorText }),
{
status: response.status,
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
}
);
}
const data = await response.json();
// 返回 Wakatime 数据
return new Response(JSON.stringify(data), {
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
});
} catch (error) {
console.error('Error fetching Wakatime data:', error);
return new Response(
JSON.stringify({ error: 'Internal server error in Worker', details: error.message }),
{
status: 500,
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
}
);
}
},
};

代码解释:

  • CORS Headers: corsHeaders 用于允许跨域请求,这在从您的 Next.js 应用 (可能在不同域名或本地开发服务器) 调用 Worker 时是必需的。
  • Environment Variable: env.WAKATIME_API_KEY 用于从 Worker 的环境变量中安全地读取您的 Wakatime API Key。切勿将 API Key硬编码到代码中。
  • Wakatime API Call: 使用 fetch 调用 Wakatime 的 summaries API 端点。
  • Error Handling: 包含对 API Key 未配置、Wakatime API 调用失败以及其他潜在错误的检查。

步骤 3: 配置并部署 Cloudflare Worker

1. 添加 Wakatime API Key 到环境变量:

  • 使用 Wrangler CLI:wrangler.toml 文件中,您可以定义 secrets。首先,通过命令行设置 secret:

    Terminal window
    # 将 YOUR_WAKATIME_API_KEY 替换为您的真实 API Key
    wrangler secret put WAKATIME_API_KEY

    Wrangler 会提示您输入 secret 值。

  • 通过 Cloudflare Dashboard:

    1. 导航到您的 Worker。
    2. 点击 “Settings” -> “Variables”。
    3. 在 “Environment Variables” 部分,点击 “Add variable”。
    4. 设置 “Variable name” 为 WAKATIME_API_KEY
    5. 设置 “Value” 为您的 Wakatime API Key。
    6. 勾选 “Encrypt” (推荐)。
    7. 点击 “Save”。

2. 配置 wrangler.toml (如果使用 Wrangler):

确保您的 wrangler.toml 文件类似如下 (根据您的项目名称调整 name):

name = "my-wakatime-worker" # 替换为您的 Worker 名称
main = "src/index.js" # 或 src/index.ts
compatibility_date = "YYYY-MM-DD" # 使用您创建项目时的日期或更新到最新
# 如果您想为 Worker 设置自定义域名/路由,可以在这里配置或在 Dashboard 中配置
# [triggers]
# routes = [ "your-domain.com/api/wakatime-stats/*" ]

3. 部署 Worker:

  • 使用 Wrangler CLI:

    Terminal window
    wrangler deploy

    部署成功后,Wrangler 会输出您的 Worker URL (例如 https://my-wakatime-worker.your-username.workers.dev)。

  • 通过 Cloudflare Dashboard: 如果您是在线编辑器中编写代码,保存更改后 Worker 会自动部署。您可以在 Worker 的概览页面找到其 URL。

4. 测试 Worker:

在浏览器中访问您的 Worker URL。如果一切配置正确,您应该能看到 Wakatime API 返回的 JSON 数据。如果看到错误,请检查 Worker 日志 (通过 Dashboard 或 wrangler tail) 和之前的配置步骤。

假设您的 Next.js 项目结构如下:

my-next-app/
├── components/
│ └── Footer.js # 我们将创建或修改此文件
├── pages/ # 或 app/ 目录 (对于 App Router)
│ └── _app.js # 或 layout.js (对于 App Router)
└── ...

创建/修改 components/Footer.js:

components/Footer.js
// src/components/Footer.js
"use client"; // 声明为客户端组件,因为使用了 useState 和 useEffect
import React, { useEffect, useState } from "react";
export default function Footer() {
const currentYear = new Date().getFullYear();
const [wakatimeText, setWakatimeText] = useState("");
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const fetchWakatimeStats = async () => {
setIsLoading(true);
setError(null);
try {
// 请将 'YOUR_WORKER_URL' 替换为您实际部署的 Cloudflare Worker URL
const workerUrl = "https://waka.yangzh.cn";
const response = await fetch(workerUrl);
if (!response.ok) {
const errorData = await response
.json()
.catch(() => ({ message: "Failed to parse error response" }));
throw new Error(
errorData.message ||
`Error fetching Wakatime stats: ${response.status}`
);
}
const result = await response.json();
// 根据您提供的 JSON 结构,我们期望数据在 result.data.text
if (result && result.data && result.data.text) {
setWakatimeText(result.data.text);
} else {
// 如果数据结构不符合预期,或者 text 字段不存在
console.warn(
'Wakatime data received, but "text" field is missing or in unexpected structure:',
result
);
setWakatimeText("Data format error");
}
} catch (err) {
console.error("Failed to fetch or process Wakatime stats:", err);
setError(err.message);
setWakatimeText("Could not load stats");
} finally {
setIsLoading(false);
}
};
fetchWakatimeStats();
}, []); // 空依赖数组确保只在组件挂载时运行一次
return (
<footer className="bg-slate-800 text-slate-300 py-8 mt-12">
<div className="container mx-auto px-4 text-center">
<p className="text-sm">
&copy; {currentYear} 《Web前端开发》课程练习平台. 保留所有权利.
</p>
<p className="text-xs mt-2">使用 Next.js 和 Tailwind CSS 构建</p>
<p className="text-xs mt-2">
Wakatime :{" "}
{isLoading ? "Loading..." : error ? `Error: ${error}` : wakatimeText}
</p>
{/* 可以在这里添加更多链接或信息 */}
</div>
</footer>
);
}

重要:YOUR_WORKER_URL 替换为您在步骤 3 中获得的实际 Cloudflare Worker URL。

总结

恭喜!您已经成功地将 Wakatime 编程时长统计集成到了您的 Next.js 应用页脚。通过使用 Cloudflare Workers 作为 API 代理,您不仅实现了功能,还确保了 Wakatime API Key 的安全。

您可以进一步扩展此功能,例如:

  • 显示更详细的统计数据 (例如,按项目或语言分类的时间)。
  • 为数据添加更美观的样式 1
  • 实现更复杂的错误处理或重试逻辑。
  • 对 Worker API 的响应进行缓存,以减少对 Wakatime API 的请求频率。

希望本教程对您有所帮助!