用 Next.js 打造实时加密货币行情追踪器

·

关键词:Next.js 开发、CoinGecko API、实时行情、React 钩子、动态路由、加密货币追踪、行情监控、币价列表、搜索引擎优化、SWR

加密货币市场 24 小时不停歇,价格波动瞬息万变。为了让普通用户也能以最友好的方式实时追踪 比特币以太坊 等主流币的 最新价格、市值与流通量,本文将手把手教你用 Next.js + CoinGecko API 搭建一个高性能、SEO 友好的加密货币行情追踪器。项目全程使用 TypeScript,可部署到 Vercel,零成本上线。


功能速览

👉 想直接跑通 Demo,点这里获取完整源码开始开发!


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-tracker

2. 项目结构一键明晰

保持目录干净,便于 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 } },
};

👉 别再手动爬数据,30 秒搞定可视化图表完整教程!


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:三步上线

  1. COINGECKO_URL=https://api.coingecko.com/api/v3 写入 vercel env add
  2. next.config.js 开启 swcMinify 优化打包体积:

    module.exports = { swcMinify: true };
  3. git push 自动触发 CI/CD,30 秒完成全球 CDN 分发。

7. SEO 进阶优化


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. 后续迭代思路


现在就把代码 clone 下来,替换 API Key 即可正式上线。祝你打造一个 速度飞起、搜索友好 的加密货币行情站,坐上 Web3 流量风口!