关键词:Next.js 开发、CoinGecko API、实时行情、React 钩子、动态路由、加密货币追踪、行情监控、币价列表、搜索引擎优化、SWR
加密货币市场 24 小时不停歇,价格波动瞬息万变。为了让普通用户也能以最友好的方式实时追踪 比特币、以太坊 等主流币的 最新价格、市值与流通量,本文将手把手教你用 Next.js + CoinGecko API 搭建一个高性能、SEO 友好的加密货币行情追踪器。项目全程使用 TypeScript,可部署到 Vercel,零成本上线。
功能速览
- 📈 实时获取 CoinGecko API 数据并自动缓存 60 秒
- 🔍 前端搜索关键词即时过滤币种
- 🪄 动态路由:点击任意币种即可进入详情页,包含 7 日历史走势小图
- 📊 响应式设计,手机、平板、桌面全覆盖
- ⚡ 使用 Next.js 14 App Router + React Suspense,首屏秒开
1. 技术栈与环境准备
| 项目要素 | 说明 |
|---|---|
| 框架 | Next.js 14 (App Router) |
| 编程语言 | TypeScript |
| 数据获取 | CoinGecko REST API |
| HTTP 库 | Axios |
| 样式 | Tailwind CSS |
| 图表 | lightweight-charts |
| Node | ≥ 18.0 |
在终端执行:
# 安装 Next.js 初始化工具
npm i -g create-next-app@latest
# 创建项目
npx create-next-app crypto-tracker --typescript --tailwind --eslint --app
cd crypto-tracker2. 项目结构一键明晰
保持目录干净,便于 SEO 路由识别:
src/
├─ app/
│ ├─ api/
│ │ └─ coins/
│ │ └─ route.ts # 自建代理,解决跨域 & 缓存
│ ├─ coins/
│ │ ├─ [id]/
│ │ │ └─ page.tsx # 动态详情页
│ │ └─ page.tsx # 币种列表
│ ├─ layout.tsx
│ └─ globals.css
├─ components/
│ ├─ CoinCard.tsx
│ ├─ SearchBar.tsx
│ ├─ PriceChart.tsx
│ ├─ SkeletonLoader.tsx
└─ utils/
└─ api.ts小贴士:把实际 API 调用封装到 utils/api.ts,方便单元测试与复用。3. 用 Server Component + SWR 自动预取数据
在 app/api/coins/route.ts 加入边缘缓存,让搜索引擎对你友好:
// CoinGecko 免费套餐每分钟限制 50 次请求
export const revalidate = 60;
export async function GET() {
const res = await fetch(
`${process.env.COINGECKO_URL}/coins/markets?vs_currency=usd&order=market_cap_desc&per_page=50`,
{ headers: { accept: 'application/json' } }
);
const data = await res.json();
return Response.json(data);
}前端使用 SWR 在客户端保持毫秒级更新:
// components/CoinList.tsx
'use client';
import useSWR from 'swr';
import CoinCard from '@/components/CoinCard';
import SkeletonLoader from '@/components/SkeletonLoader';
const fetcher = (url: string) => fetch(url).then(r => r.json());
export default function CoinList() {
const { data, error } = useSWR('/api/coins', fetcher, {
suspense: true,
refreshInterval: 60000,
revalidateOnFocus: true,
});
if (error) return <p>加载失败</p>;
if (!data) return <SkeletonLoader count={10} />;
return (
<section className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{data.map((coin) => (
<CoinCard key={coin.id} coin={coin} />
))}
</section>
);
}4. 动态详情页:Tailwind 暗黑模式 + 图表
在 app/coins/[id]/page.tsx 先 预取币名,返回 包含 OpenGraph 标签 的元数据:
export async function generateMetadata({ params }: Props) {
const coin = await fetchCoinDetail(params.id);
return {
title: `${coin.name} 实时行情 - Crypto Tracker`,
description: `${coin.name} 最新价格 ${coin.current_price} USD,市值 ${coin.market_cap},CoinGecko 官方数据。`,
};
}引入 lightweight-charts 绘制 K 线缩略图:
const options = {
width: 500,
height: 220,
priceScale: { scaleMargins: { top: 0.2, bottom: 0.2 } },
grid: { vertLines: { visible: false }, horzLines: { visible: false } },
};5. 搜索 + 高亮关键字
使用 Next.js 内置客户端搜索(防抖 300 ms):
// components/SearchBar.tsx
export default function SearchBar({ value, onChange }) {
const [inner, setInner] = useState(value);
useEffect(() => {
const timer = setTimeout(() => onChange(inner), 300);
return () => clearTimeout(timer);
}, [inner, onChange]);
return (
<input
value={inner}
onChange={(e) => setInner(e.target.value)}
placeholder="搜索比特币、ETH..."
className="w-full md:w-72 px-4 py-2 rounded border border-slate-300 dark:border-slate-700"
/>
);
}父组件过滤逻辑:
const filtered = data.filter(c => c.name.toLowerCase().includes(q.toLowerCase()));6. 部署到 Vercel:三步上线
- 把
COINGECKO_URL=https://api.coingecko.com/api/v3写入vercel env add 在
next.config.js开启swcMinify优化打包体积:module.exports = { swcMinify: true };git push自动触发 CI/CD,30 秒完成全球 CDN 分发。
7. SEO 进阶优化
- 静态元数据:将所有列表页、标签页自动写入
sitemap.xml Link预加载:loading="lazy"结合 Next.jsImage减少带宽- 结构化数据:用
application/ld+json输出 FAQ & Product JSON-LD 让谷歌富摘要展示涨跌幅 - CLS 清零:卡片高度固定,避免布局跳动
8. 常见问题 FAQ
Q1:CoinGecko 免费配额不够怎么办?
A:可把 revalidate 拉高至 120 秒,并本地做内存/Redis 双层缓存。付费 API 每分钟可达 500 次。
Q2:如何实现价格波动提醒?
A:调用 Firebase Cloud Messaging,把用户设置的阈值存进 Firestore,使用 Cloud Functions 定时轮询,再推送通知。
Q3:为什么刷新详情页后出现 CSR 加载闪烁?
A:在 page.tsx 使用 React.Suspense 包裹 <PriceChart>,并且在 loading.tsx 渲染骨架屏即可消除闪烁。
Q4:能否直接在前端暴露在公网调用 CoinGecko?
A:强烈建议自建 /api/coins 代理,一来避免 CORS,二来可统一限流、缓存,提升 SEO。
Q5:如何做代码拆分?
A:利用 next/dynamic,图表组件仅在客户端加载:
const Chart = dynamic(() => import('@/components/PriceChart'), { ssr: false });Q6:部署后还能加广告吗?
A:禁止投放任何形式的嵌入式广告,可保持开源状态,在 GitHub README 中加入 非侵入式赞助链接 即可。
9. 后续迭代思路
- 接入 WebSocket 实时推送
- 支持多语种本地化文件
messages/[lang].json - 增加投资组合功能:用户增删币种并本地持久化到 IndexedDB
- 接入 Google Analytics 4 事件,追踪搜索关键词,反哺 SEO 策略
现在就把代码 clone 下来,替换 API Key 即可正式上线。祝你打造一个 速度飞起、搜索友好 的加密货币行情站,坐上 Web3 流量风口!