Vercel Edge Functions 跑在 V8 isolate 上、离用户最近、冷启动几十毫秒——听起来稳赚。但别忘了预生成的静态页比这还快,而 Node serverless 能用全套 npm。本文讲清 Edge 在内容站上什么时候是对的工具,什么时候反而吃亏。
问题背景
Vercel 有三种计算目标:静态(build 时预生成)、Node serverless(完整 Node 运行时,冷启动约 300ms)、Edge Functions(V8 isolate,冷启动约 50ms,跑在 18+ 区域)。Edge 有硬限制:不能用原生 Node 模块、代码 4 MB 上限、请求体 1.5 MB、API 受限。内容站绝大部分应该走静态,其余情况本文讨论。
判断标准
- 每次页面加载都打函数,真实用户指标里看得到冷启动尖刺。
- 在服务页面之前就要做地理路由、A/B 测试或鉴权——不是之后。
- 函数体积小(1 MB 以内)、纯 JS、不需要文件系统或原生模块。
- 离函数区域远的用户 TTFB 明显高。
快速结论
如果干的活是”重写、跳转、按地区分流、设 cookie、读 header”——Edge 赢。如果是”渲染页面、生成 OG 图、用胖 ORM 查数据库”——选 Node serverless,或者直接预生成。纯内容站静态胜过两者。
Edge Functions 真正有优势的场景
三个 Edge 在内容站上明显比 Node serverless 强的模式:
- 中间件里的按地区跳转。 根据
Accept-Language或国家码把/跳到/en/或/zh/——Edge 跑在缓存前,开销大概 20ms:
// middleware.ts
import { NextResponse, NextRequest } from 'next/server';
export const config = { matcher: ['/'] };
export function middleware(req: NextRequest) {
const country = req.geo?.country ?? 'US';
const lang = country === 'CN' || country === 'TW' ? 'zh' : 'en';
return NextResponse.redirect(new URL(`/${lang}/`, req.url));
}
- 带 cookie 持久化的 A/B 测试。 首次访问分桶、写 cookie、之后保持稳定。分桶决策必须在缓存之前,中间件正合适:
// middleware.ts —— 分桶并重写到变体
import { NextResponse, NextRequest } from 'next/server';
export const config = { matcher: ['/pricing'] };
export function middleware(req: NextRequest) {
const existing = req.cookies.get('ab-pricing')?.value;
const bucket = existing ?? (Math.random() < 0.5 ? 'a' : 'b');
const url = req.nextUrl.clone();
url.pathname = `/pricing-${bucket}`;
const res = NextResponse.rewrite(url);
if (!existing) {
res.cookies.set('ab-pricing', bucket, { maxAge: 60 * 60 * 24 * 30 });
}
return res;
}
- 鉴权预览。 在边缘读 session cookie,把草稿重写到 preview 分支,没权限的直接拦下,不用回 Node origin。
值得记一下的真实延迟数字
2026 年 Vercel 的粗略预算,us-east-1、热缓存:
- CDN 上的静态页:TTFB 20-40ms。
- Edge Function(热):在 CDN 之上再加 30-60ms TTFB——匹配到的路由上,函数仍在缓存之前跑。
- Edge Function(冷):某区域首次请求 80-150ms。
- Node serverless(热):100-200ms。
- Node serverless(冷):300-1500ms,看 bundle 大小。
如果用户全球、函数干的活又轻,Edge 冷启动可能比 Node 热还低。如果函数被命中得少,Node 冷启动就是最坏情况。
该用 Node serverless 的场景
- 用
@vercel/og生成 OG 图、字体从 CDN 加载——Edge 能跑,但需要从文件系统加载资源时 Node 更舒服。 - API 路由要打 Prisma、Drizzle 或任何官方还没正式支持 Edge 的 ORM——大部分仍然要 Node。
- 任何用原生依赖的:
sharp、puppeteer、node-canvas——这些在 Edge 上根本跑不起来。
两者都不对、静态才赢的场景
- 内容按已知节奏更新的文章页。build 时预生成,更新走 ISR 或 on-demand revalidation,函数完全省掉。
- sitemap 和 robots——build 时生成,CDN 直出,零函数调用。
- 数据量在 200 KB 以内的搜索 / 过滤 UI——跟着页面发出去,前端直接过滤。
容易踩的坑
- “为了个性化”把文章页放到 Edge Function 后面——CDN 缓存全废,每次请求都多一份延迟。
- 在 Edge route 里 import 了 Node-only 模块,部署时才发现——本地 dev 也要设
runtime = 'edge'。 - 忘了 Edge Function 即便命中 304 也计用量——中间件跑在缓存之前。
- 在 Edge 里读集中式数据库——函数快,但从各地区回数据库的 round trip 一点不快。要么用全球复制存储(Upstash、PlanetScale edge driver),要么预生成。
- 用 Edge 做 OG 图,bundle 字体后撞 4 MB 上限——换 Node。
FAQ
- Edge Functions 比 Node serverless 便宜吗?: 单次调用通常便宜。但中间件每次请求都跑,逻辑放错位置反而总成本更高。
- Pages Router 能用 Edge Functions 吗?: 能,API 路由里
export const config = { runtime: 'edge' },或者写middleware.ts。 - Edge 上能用哪些 API?: Web 标准 API(fetch、Request、Response、crypto.subtle、streams)。没有
fs、没有原生模块、Buffer也受限。 - Astro 支持 Edge 吗?:
@astrojs/verceladapter 有edge模式,但大多数 Astro 站是静态的,根本不需要。 - Edge 会让我 Lighthouse 分数变高吗?: 仅当你的 TTFB 卡在 Node 冷启动上才有用。配好缓存头的静态页 Lighthouse 上已经赢了。