Next.js 15 Server Actions 与 GraphQL/REST 混合缓存与再验证策略概述将 Server Actions 用于同步/表单场景与轻交互写入;查询侧采用 GraphQL(Apollo)与 REST(SWR/React Query)混合缓存,协同标签失效与 ETag 再验证,确保性能与一致性。技术背景App Router/RSC、PPR、`revalidateTag/revalidatePath`;`unstable_cache` 与 Edge 缓存;Apollo 的 `InMemoryCache` 与 Persisted Queries;REST 使用 `ETag/If-None-Match`。写入:Server Actions 与乐观更新// app/actions.ts 'use server' import { z } from 'zod' import { revalidateTag } from 'next/cache' const schema = z.object({ id: z.string(), title: z.string().min(1) }) export async function savePost(formData: FormData) { const data = Object.fromEntries(formData) const parsed = schema.safeParse(data) if (!parsed.success) return { ok: false, errors: parsed.error.flatten() } await db.post.upsert(parsed.data) // 写入数据库 revalidateTag('posts') // 使 posts 列表失效 return { ok: true } } 查询:GraphQL 与 REST 缓存协同// graphql/client.ts import { ApolloClient, InMemoryCache, createHttpLink } from '@apollo/client' export const client = new ApolloClient({ link: createHttpLink({ uri: '/api/graphql', fetchOptions: { cache: 'no-store' } }), cache: new InMemoryCache({ addTypename: true }) }) // REST 再验证(ETag) export async function fetchWithETag(url: string, etag?: string) { const res = await fetch(url, { headers: etag ? { 'If-None-Match': etag } : {} }) if (res.status === 304) return { fromCache: true } return { data: await res.json(), etag: res.headers.get('ETag') } } 服务器端缓存与 PPR// 数据获取:RSC 中使用 unstable_cache import { unstable_cache } from 'next/cache' const getPosts = unstable_cache(async () => { const res = await fetch('https://api.example.com/posts', { next: { tags: ['posts'] } }) return res.json() }, ['posts'], { revalidate: 600 }) export const dynamic = 'force-static' // PPR 友好 边缘再验证与 Persisted Queries// app/api/graphql/route.ts(简化) import { NextResponse } from 'next/server' export async function POST(req: Request) { const { id, variables } = await req.json() // Persisted Query id const result = await executePersistedQuery(id, variables) return NextResponse.json(result, { headers: { 'Cache-Control': 'public, max-age=60', 'ETag': hash(result) } }) } 技术参数与验证Node.js: 20.x;浏览器:Chrome 120+LCP < 2.5s;列表 `revalidateTag` 命中率 > 85%;GraphQL Persisted Queries 缓存命中 > 80%REST ETag 命中率 > 70%;PPR 首屏就绪时间稳定在 1.8-2.4s应用场景内容型站点:列表与详情的混合数据层SaaS 控制台:设置表单写入 + 列表查询一致性注意事项Server Actions 仅用于可信写入;避免在客户端滥用副作用`revalidateTag` 需与 `unstable_cache` 标签一致;GraphQL/REST 的缓存层需统一失效策略常见问题Q: GraphQL 与 REST 可以并存吗?A: 可以,保持规范化的域模型与统一失效策略即可。参考资料Next.js Cache & Tags 文档Apollo Client 缓存与 Persisted QueriesHTTP 缓存头与 ETag 规范---发布信息:已发布 · 技术验证 · 阅读 38 分钟 · CC BY-SA 4.0

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论
立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部
1.384738s