编程 Edge Runtime 不是 CDN 上的 Node.js:Next.js 16.3 起 runtime = 'edge' 已不再支持

2026-10-09 00:03:23

Edge Runtime 不是 CDN 上的 Node.js:Next.js 16.3 起 runtime = 'edge' 已不再支持

Edge Runtime 是基于 V8 isolate 的独立运行时,不是把 Node.js 搬到 CDN 上。它没有容器、没有虚拟机、没有持久进程,写法和限制都跟跑在源站的 Node.js 不是一回事。

这到底是什么

Vercel 官方文档(https://vercel.com/docs/functions/runtimes/edge)的描述是:

  • Edge Runtime 构建在 V8 引擎上,运行在隔离的执行环境里,不需要容器或虚拟机。
  • 默认在离请求最近的区域执行,可以用路由段配置 preferredRegion,或 config 里的 regions 指定区域。
  • 某个区域故障时,自动把流量转到最近的 CDN 区域(failover)。

Cloudflare Workers 那边是同一套底层思路:两者都跑 V8 isolates 而不是容器,单进程多租户,JS 引擎级隔离,冷启动接近 0ms(isolate 初始化 <1ms)。Cloudflare Workers 的运行时叫 workerd,开源,可以用 Wrangler 在本地跑起来。

支持和不支持的 API

Edge Runtime 提供的是一个 Web API 子集:fetch、Request、Response、Web Crypto、Streams、URL。

不支持的部分:

  • 文件系统读写。
  • 直接调用 require,要用 import。
  • 动态代码执行 eval 因安全原因不可用,依赖 eval 的库会在运行时报错。
  • 除上面列出的之外,多数 Node.js API 不可用。

node_modules 是能用的,前提是 ESM,并且不依赖原生 Node API。

workerd 暴露的 API 比 Vercel Edge 更全一些:带完整 backpressure 的 Streams、服务端 WebSocket(Durable Objects 可休眠)、Cache API、Worker 间 RPC 子请求、WebCrypto 含 key wrapping。Vercel Edge 用的是常用子集,长连接、实时、服务端推送方面受限更多。

硬限制对照表

项目Cloudflare WorkersVercel Edge
内存128MB128MB
CPU 预算免费 10ms;付费默认 30s,可配到 5 分钟(同步 CPU)无独立 CPU 预算
挂钟超时I/O wait 不计入 CPU,但计入挂钟Middleware 1000ms;函数 25s 首字节 / 300s 流式
bundle免费 1MB / 付费 5MB 未压缩(gzip 后 3MB / 10MB,压缩前 64MB)1–4MB(取决于套餐);Edge Middleware 1MB 未压缩

状态原语方面,Cloudflare 有 KV、R2、Durable Objects、D1;Vercel 有 Edge Config、Vercel KV、Blob。

CPU 时间不等于挂钟时间

这两个不是一个东西,混淆了很容易把预算算错。

Cloudflare 的 CPU 预算指的是同步 CPU 时间:免费 10ms,付费默认 30s,可配到 5 分钟。出站 fetch、KV 读这类 I/O wait 不计入 CPU,但计入挂钟时间——等一个慢接口不会烧掉 CPU 预算,但请求本身会一直挂着。

Vercel Edge 没有独立的 CPU 预算这一说,卡的是挂钟:Edge Middleware 的挂钟超时是 1000ms,函数必须在 25 秒内开始发送响应以保持流式能力,之后最多可持续流式 300 秒。

边缘连数据库的延迟陷阱

Edge 不是完整的服务器环境,是另一套思维模型。

先看限制:没有原生模块,bcrypt、sharp、canvas 这类 C++ 绑定用不了;没有持久连接,isolate 是临时的,请求之间无法保持数据库连接,请求处理完可能被回收。

然后是延迟。你的数据库在一个区域,edge 在 300+ 区域。每次查询都要从 edge 节点跨到数据库所在区域再返回,上游数据库和 API 的延迟往往主导整体延迟——边缘就近执行省下来的那点时间,被这一跳吃掉了。

打包体积也卡得死:Cloudflare 1MB(免费)/ 5MB(付费),Vercel Edge 4MB(压缩后),Deno Deploy 20MB。

所以 Edge 适合的是在请求到达源站前做快速决策:守门人、路由器、转换器,不是应用服务器。把快的部分放这里——鉴权、重定向、A/B、本地化、feature flag;慢的部分——DB 查询、重活——留给源站。

Next.js 16.3 撤掉 runtime = 'edge'

Vercel 现在的建议是从 edge 迁移到 Node.js,理由是性能与可靠性提升,两者都跑在 Fluid compute + Active CPU 计费上。

关键变化:从 Next.js 16.3 开始,设置 runtime = 'edge' 不再被支持,路由和页面统一跑在 Node.js 上。

另外,Next.js middleware 始终跑在 edge——这是设计如此,它会拦截每一个匹配的请求。

其他平台的情况:Deno Deploy(V8 + 原生 Deno API,TypeScript 原生,20MB 包)、Fastly Compute@Edge(以 WASM 为基础,支持多语言)、Netlify Edge Functions(Deno 运行时)。

该用在哪儿

判断标准就一条:这段代码是不是在请求到达源站之前做决策。

适合:鉴权、重定向、A/B 分流、本地化、feature flag 读取。这些操作输入输出都小,不碰原生模块,一两次 fetch 或一次 KV / Edge Config 读取就能结束。

不适合:需要数据库连接池的查询、图像处理、PDF 生成、加密哈希(bcrypt 这类)、任何依赖 eval 的库、任何需要长连接或服务端推送的场景。

怎么判断当前在不在 edge

检查全局属性 globalThis.EdgeRuntime:

if (typeof globalThis.EdgeRuntime !== 'undefined') {
  // 运行在 Edge Runtime
}

这个判断在需要给同一份代码写两条分支时有用——比如在 edge 里走 fetch 调外部服务,在 Node.js 里直接查库。

推荐文章

程序员茄子在线接单