在Next.js中限制对Hygraph的API调用次数
针对你用Next.js + Hygraph的场景,结合数据更新频率低的特点,推荐几个不用额外部署复杂服务的简便方案,能大幅减少API调用量:
1. 用Next.js静态生成(SSG)+ 增量静态再生(ISR)彻底减少前端请求
Next.js的静态生成是最适合低频更新数据的场景——在构建阶段就把所有页面的Hygraph数据预拉取并生成静态HTML,用户访问时直接加载静态文件,完全不触发API调用。如果数据需要更新,不用全量重新构建,用ISR可以指定页面的刷新间隔,自动后台更新数据。
比如把你的Team页面改成动态路由(pages/team/[slug].js),用getStaticProps和getStaticPaths实现:
export async function getStaticPaths() { // 先拉取所有team的slug列表(这一步只在构建时执行一次) const allTeams = await getAllTeamSlugs(); const paths = allTeams.map(team => ({ params: { slug: team.slug } })); // 如果slug太多,用fallback: true实现增量生成,不用一次性构建所有页面 return { paths, fallback: true }; } export async function getStaticProps({ params }) { // 构建时/ISR刷新时拉取对应slug的team数据 const profile = await getTeamProfile(params.slug); return { props: { profile }, // 设置每24小时自动刷新页面数据(根据你的更新频率调整) revalidate: 86400 }; } const Team = ({ profile }) => { // 直接用props里的profile,不用useEffect请求 // Rest of the code }
这样大部分用户访问都是加载静态页面,只有ISR刷新或者新增slug时才会调用Hygraph API,调用量会骤降。
2. 客户端侧用缓存库复用请求结果
如果某些页面没办法用静态生成,可借助SWR或React Query这类缓存库,它们会自动缓存请求结果,相同slug的重复请求直接用缓存,不用再调用API。
比如用SWR改造你的代码:
import useSWR from 'swr'; const Team = () => { const router = useRouter(); const { slug } = router.query; // SWR会自动缓存getTeamProfile的请求结果,相同slug再次访问直接取缓存 const { data: profile } = useSWR(router.isReady ? ['team-profile', slug] : null, () => getTeamProfile(slug), { // 设置缓存有效期,比如1天(根据数据更新频率调整) revalidateOnMount: false, revalidateIfStale: false, revalidateOnFocus: false, staleTime: 86400000 }); // Rest of the code }
这样同一个用户多次访问同一个团队页面,只会发起一次API请求,后续用缓存。
3. 配置Hygraph的CDN缓存
Hygraph本身自带CDN,你可以在请求时设置Cache-Control头,让CDN缓存GraphQL响应,相同的查询请求会直接从CDN返回,不用消耗你的API调用额度。
修改你的getTeamProfile函数,添加缓存头:
async function getTeamProfile(slug) { const res = await fetch(process.env.HYGRAPH_API_URL, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${process.env.HYGRAPH_API_TOKEN}`, // 设置缓存1天,根据数据更新频率调整 'Cache-Control': 's-maxage=86400, stale-while-revalidate' }, body: JSON.stringify({ query: gql` query GetTeamProfile($slug: String!) { team(where: {slug: $slug}) { // 你的字段 } } `, variables: { slug } }) }); const data = await res.json(); return data.data.team; }
这样重复的查询会被Hygraph的CDN缓存,直接返回给客户端,不会消耗你的调用次数。
4. 合并GraphQL查询减少请求次数
如果你的页面需要多个Hygraph数据(比如团队信息+成员列表),不要分开发起多次请求,把多个查询合并成一个GraphQL请求,一次获取所有需要的数据,减少API调用次数。
比如原来可能两次请求,现在合并成一个:
async function getTeamWithMembers(slug) { const res = await fetch(process.env.HYGRAPH_API_URL, { method: 'POST', headers: { /* 头信息 */ }, body: JSON.stringify({ query: gql` query GetTeamWithMembers($slug: String!) { team(where: {slug: $slug}) { name description members { name role } } } `, variables: { slug } }) }); // ...处理数据 }
这些方案都比部署中转服务器或对象存储更简便,优先用静态生成+ISR,能从根源上减少API调用量,再配合客户端缓存和CDN缓存,完全可以把调用量控制在免费额度内。
内容的提问来源于stack exchange,提问作者Rachid Rajjys

