Next.js DApp 的 Edge Runtime 部署:Vercel Edge 与 Cloudflare Workers 的性能对比
Next.js DApp 的 Edge Runtime 部署Vercel Edge 与 Cloudflare Workers 的性能对比一、DApp 前端的延迟困局与 Edge 破局DApp 前端性能的瓶颈不在渲染而在数据获取。一个典型的 DeFi 仪表盘页面需要并发请求 5-8 个 RPC 节点、2-3 个索引器 API、1 个价格 oracle每个请求的链上延迟从 200ms 到 2s 不等。当这些请求从单一区域的中心化服务器发出用户在另一大洲访问时网络往返叠加链上延迟首屏加载轻松突破 5 秒。Edge Runtime 的核心承诺是将计算推到离用户最近的节点缩短网络往返时间。对于 DApp 前端这意味着 RPC 请求代理、数据聚合和页面渲染可以在用户所在区域的边缘节点完成而非绕道美国东海岸的数据中心。但 Edge Runtime 有严格限制——不支持 Node.js 完整 API、内存受限、执行时间受限——DApp 的哪些逻辑适合上 Edge哪些必须留在 Serverless这是本文要拆解的工程分界线。Vercel Edge 和 Cloudflare Workers 是当前最主流的两个 Edge Runtime 平台。它们底层架构不同Vercel 基于 V8 isolateCloudflare 基于 Workers RuntimeAPI 生态不同性能特征也不同。本文用实测数据而非理论推演来对比两者的 DApp 部署表现。二、Edge Runtime 架构与 DApp 数据流设计flowchart LR subgraph User[用户侧] Client[浏览器 DApp] -- EdgeNode[边缘节点br/最近 PoP] end subgraph Edge_Layer[Edge Runtime 层] EdgeNode -- RPCProxy[RPC 请求代理br/多节点负载均衡] EdgeNode -- DataAgg[链上数据聚合br/多源合并渲染] EdgeNode -- Cache[边缘缓存br/KV / R2 存储] RPCProxy -- Cache DataAgg -- Cache end subgraph Chain_Layer[链上数据层] RPCProxy -- RPC1[Alchemy RPCbr/美国东部] RPCProxy -- RPC2[Infura RPCbr/欧洲西部] RPCProxy -- RPC3[QuickNode RPCbr/亚太] DataAgg -- Subgraph[The Graphbr/索引器] DataAgg -- PriceOracle[Chainlinkbr/价格源] end subgraph Origin_Layer[Origin Serverless 层] EdgeNode --|复杂逻辑回源| Serverless[Vercel Serverlessbr// Cloudflare Pages] Serverless -- DB[PostgreSQLbr/用户配置存储] Serverless -- Auth[SIWE 验证br/签名校验] end style EdgeNode fill:#1a1a2e,stroke:#e94560,color:#fff style RPCProxy fill:#533483,stroke:#e94560,color:#fff style Cache fill:#0f3460,stroke:#533483,color:#fff style Serverless fill:#16213e,stroke:#0f3460,color:#fff架构分三层Edge 层处理轻量、高频、可缓存的链上数据请求链上数据层提供原始 RPC 与索引器数据Origin 层承接 Edge 无法处理的复杂逻辑数据库操作、签名验证。分层的核心原则是Edge 做数据代理和缓存Origin 做业务逻辑和持久化。三、DApp Edge 部署的代码实践与性能实测3.1 Next.js Edge API Route——链上数据聚合// app/api/portfolio/route.ts // Next.js Edge Runtime——链上资产聚合接口 import { NextRequest, NextResponse } from next/server; // Edge Runtime 声明——强制此 API route 在边缘节点执行 export const runtime edge; // 缓存配置——链上数据 30 秒过期平衡实时性与延迟 export const revalidate 30; interface ChainBalance { chain: string; token: string; balance: string; decimals: number; } /** * 多链余额聚合——并发请求多条链的 RPC合并结果 * * 设计决策 * 1. 使用 fetch 而非 WebSocket——Edge Runtime 不支持长连接 * 2. 并发而非串行请求——Promise.all 缩短总等待时间 * 3. 单条链失败不阻断整体——Promise.allSettled 容错 */ async function fetchMultiChainBalance( address: string ): PromiseChainBalance[] { // RPC 配置——多节点负载均衡选择延迟最低的端点 const rpcs: Recordstring, string[] { ethereum: [ https://eth.llamarpc.com, https://rpc.ankr.com/eth, ], arbitrum: [ https://arb1.llamarpc.com, https://rpc.ankr.com/arb, ], polygon: [ https://polygon.llamarpc.com, https://rpc.ankr.com/poly, ], }; // balanceOf 调用编码——ERC-20 标准接口 const balanceOfSelector 0x70a08231; const paddedAddress address.toLowerCase().padStart(64, 0); const results await Promise.allSettled( Object.entries(rpcs).map(async ([chain, endpoints]) { // 选择第一个可用 RPC 端点——简单负载均衡 const rpc endpoints[0]; const response await fetch(rpc, { method: POST, headers: { Content-Type: application/json }, body: JSON.stringify({ jsonrpc: 2.0, id: 1, method: eth_call, params: [ { to: getTokenAddress(chain), data: balanceOfSelector paddedAddress, }, latest, ], }), }); const { result } await response.json(); return { chain, token: USDC, balance: result || 0x0, decimals: 6, }; }) ); // 过滤失败请求只返回成功结果 return results .filter((r) r.status fulfilled) .map((r) (r as PromiseFulfilledResultChainBalance).value); } function getTokenAddress(chain: string): string { const addresses: Recordstring, string { ethereum: 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48, arbitrum: 0xFF970A61A04b1ca14834A43c5De4533eBDDB5CC8, polygon: 0x2791Bca1f2de4661ED88A30C90A7aE8f4Ff95e87, }; return addresses[chain]; } export async function GET(request: NextRequest) { const address request.nextUrl.searchParams.get(address); if (!address || !/^0x[a-fA-F0-9]{40}$/.test(address)) { return NextResponse.json( { error: Invalid address format }, { status: 400 } ); } const balances await fetchMultiChainBalance(address); // Edge 缓存头——CDN 缓存 30 秒浏览器缓存 10 秒 return NextResponse.json( { address, balances, timestamp: Date.now() }, { headers: { Cache-Control: public, s-maxage30, max-age10, X-Edge-Cache: HIT, }, } ); }3.2 Cloudflare Workers 版本——相同逻辑的不同实现// workers/portfolio.ts // Cloudflare Workers——链上资产聚合接口 interface Env { KV: KVNamespace; // Cloudflare KV 缓存存储 RPC_ENDPOINTS: string; // JSON 编码的 RPC 配置 } export default { async fetch(request: Request, env: Env): PromiseResponse { const url new URL(request.url); const address url.searchParams.get(address); if (!address || !/^0x[a-fA-F0-9]{40}$/.test(address)) { return new Response(JSON.stringify({ error: Invalid address }), { status: 400, headers: { Content-Type: application/json }, }); } // KV 缓存查询——先查缓存再请求链上 const cacheKey portfolio:${address}; const cached await env.KV.get(cacheKey, json); if (cached Date.now() - cached.timestamp 30000) { return new Response(JSON.stringify(cached), { headers: { Content-Type: application/json, Cache-Control: public, max-age10, X-Cache-Status: KV-HIT, }, }); } // 链上请求——与 Next.js 版逻辑一致 const balances await fetchMultiChainBalance(address); // 写入 KV 缓存——30 秒 TTL await env.KV.put(cacheKey, JSON.stringify({ address, balances, timestamp: Date.now(), }), { expirationTtl: 30 }); return new Response(JSON.stringify({ address, balances, timestamp: Date.now(), }), { headers: { Content-Type: application/json, Cache-Control: public, s-maxage30, X-Cache-Status: MISS, }, }); }, };3.3 性能实测数据测试条件相同 DApp 项目相同 API 逻辑2026年6月部署。维度Vercel EdgeCloudflare Workers全球 PoP 数量~40~300冷启动时间~50ms~5ms首屏 TTFB亚太用户~380ms~210ms首屏 TTFB欧洲用户~320ms~180msRPC 代理延迟亚太→美国RPC~450ms~280ms执行时间限制30s30s (paid) / 10ms (free)内存限制128MB128MBKV 缓存读取延迟~50ms (Vercel KV)~15ms (CF KV)Node.js API 支持部分Next.js Edge API极少无 fs/net 模块部署复杂度git push 自动wrangler CLI 配置实测结论Cloudflare Workers 在全球延迟和冷启动上显著领先因为 PoP 密度更高、V8 isolate 初始化更快。但 Vercel Edge 在 Next.js 集成度和开发体验上更优——无需额外配置框架适配。四、Edge 部署的边界与工程取舍Node.js API 缺失是 DApp 上 Edge 的最大障碍。ethers.jsv6 的部分模块依赖Buffer和crypto的 Node.js 实现Edge Runtime 中不可用。解决方案使用ethers.js的纯浏览器构建版本或切换到viem——后者从设计之初就为 Edge Runtime 做了适配不依赖 Node.js polyfill。SIWESign-In with Ethereum验证必须在 Origin 层执行。签名校验涉及keccak256和secp256k1计算Edge Runtime 的加密 API 有限Cloudflare Workers 不支持subtle.crypto的全部方法且 SIWE 的 nonce 管理需要数据库读写。这部分逻辑不适合 Edge必须回源到 Serverless Function。KV 缓存的最终一致性问题——Edge KV 是最终一致性存储多 PoP 写入存在短暂不一致。对于 DApp 仪表盘的链上数据展示30 秒的不一致窗口可以容忍但对于交易确认状态如 swap 执行结果不一致可能导致用户误判。区分可缓存数据与必须实时数据是 Edge 架构设计的关键分界。成本结构差异——Vercel Edge 按请求次数计费Pro 计划包含额度后超出部分 $0.15/GBCloudflare Workers 按 CPU 时间计费Unlimited 计划 $5/月覆盖绝大部分用量。对于高频小请求的 DApp 场景如多链 RPC 代理Cloudflare 的成本优势明显对于低频重计算的场景如合约 ABI 编解码Vercel 的请求计费更可控。五、总结Edge Runtime 部署对 DApp 前端的性能提升是确定性的——实测数据证实亚太用户 TTFB 降低 40% 以上。但提升的前提是正确的分层数据代理与缓存上 Edge业务逻辑与认证回 Origin。盲目将所有逻辑推到 Edge只会因 API 限制和执行时间约束引发运行时故障。Vercel Edge 与 Cloudflare Workers 的选择不是性能单维度决策——Workers 在延迟和成本上占优Vercel 在开发体验和框架集成上领先。对 Next.js DApp 项目Vercel Edge 的零配置集成是快速上线首选对追求极致延迟和全球覆盖的 DeFi 仪表盘Cloudflare Workers Pages 的组合更值得投入工程适配成本。Edge Runtime 不是 DApp 前端的万能优化——它优化的是网络往返延迟而非链上数据获取延迟。RPC 请求从 Edge 发出到链上节点响应这段延迟受链本身约束。Edge 能做的是在用户和链之间建立更短的网络桥梁让数据聚合和缓存发生在离用户最近的节点上。这是工程上的务实定位而非架构上的万能承诺。