导读:2026 年 10 月 9 日,Deno 团队整体加入 Cloudflare:运行时再维护一年,Deploy 六个月后关停。两年前的同一天,Deno 2 发布,宣布全面兼容 Node。
一个由 Node 之父创办、融资 2600 万美元、拿下 10 万星的运行时,为什么在第八年停下?答案不在性能,而在迁移成本、部署错配与一门生意的时钟。
▲ Cloudflare 与 Deno 的联合公告(图源:Cloudflare Blog)
2026 年 10 月 9 日,两条博客几乎同时发出。一条在 deno.com,署名 Ryan Dahl;一条在 blog.cloudflare.com,署名 Ryan Dahl 和 Kenton Varda。两篇文章说的是同一件事:Deno 的整个团队加入 Cloudflare,Deno 运行时再维护一年,之后结束官方开发;Deno Deploy 继续运行六个月,然后关停;JSR 保留,基础设施迁往 Cloudflare;rusty_v8 继续维护,并计划整合进 Cloudflare 的 workerd。
公告写得很平静。Ryan 说,团队要把未来的开发工作放进这个共享平台,而不是继续维护一个独立的运行时和托管服务。Kenton 说,Cloudflare 很高兴,因为 Deno 团队做出了他们一直想做的 celld。交易金额没有披露,双方也没有解释估值。对外界来说,最重要的信息只有一句:Deno 运行时进入了倒计时。
时间上有一个不易察觉的对称。2024 年 10 月 9 日,Deno 2 发布,主题是全面兼容 Node 与 npm。两年后的同一天,Deno 团队宣布停止运行时开发。Deno 2 是这家公司最大的一次妥协,也是它试图扩大用户面的收尾之作;而这次告别,恰好落在同一个日期上。
一份后悔清单
要理解 Deno 为什么停下,得先回到它为什么出发。
2009 年,Ryan Dahl 在 JSConf EU 上用一段五百行的 JavaScript IRC 服务器演示了 Node.js。真正让人兴奋的地方在于它证明了一件事:JavaScript 不只能跑在浏览器里,也能用一个纯异步的模型处理大量并发连接,代码量反而不是重点。此后十年,Node.js 成了服务端 JavaScript 的事实标准,npm 成了世界上最大的软件注册表,围绕它长出了一整代 Web 框架、构建工具和云平台。
2018 年,Ryan 在同一个会议上做了一场后来被反复引用的演讲,《10 Things I Regret About Node.js》。他列出的问题包括没有坚持 Promise、默认没有安全边界、GYP 构建系统、package.json 与 node_modules 的设计、require 的解析规则。那场演讲的结尾,他公布了 Deno:一个默认安全、原生支持 TypeScript 和 ES Modules 的新运行时。Deno 最初用 Go 写,后来换成 Rust,最终在 2020 年以 Rust + V8 + Tokio 的形态发布 1.0。
Deno 的名字来自一个字符串操作:"node".split('').sort().join(''),把 node 的字母重新排列,就得到 deno。这个命名本身就是一份宣言。Deno 从第一天起就不是 Node 的升级版,而是 Node 的反面:Node 默认信任代码,Deno 默认不信任;Node 用 CommonJS 和 node_modules,Deno 用 URL 导入和全局缓存;Node 把格式化、测试、打包留给社区,Deno 把它们塞进一个可执行文件;Node 要先把 TypeScript 编译成 JavaScript,Deno 直接运行 .ts。
2020 年 5 月,Deno 1.0 发布。那几年,它确实吸引了一批被 Node 工具链折磨过的开发者。一个人写脚本、做 CLI、搭小网站,Deno 的体验是完整的:不需要 tsconfig.json,不需要 jest,不需要 prettier,不需要 nodemon。一个二进制文件,几乎什么都能做。
Deno 的权限模型在当时是新鲜的:默认不能读文件、不能联网、不能读环境变量,要显式 --allow-read、--allow-net。对一个要运行陌生人代码的平台来说,这个设计非常有吸引力;但对一个普通的 Web 服务来说,它更像是一层需要额外配置的保险。安全是 Deno 最好的差异化,也是最难被日常开发感知的差异化。
这也是 Deno 最早、最牢固的用户群:个人项目、内部工具、边缘脚本。它的问题也埋在这里------这些场景的用户很多,但付费意愿和迁移决心都很有限。
开发者世界的大部分代码不是新写的。一个 2015 年上线的电商系统,不会因为新运行时更优雅就重写;它只会问三个问题:现有依赖能不能跑,部署流水线要不要改,出问题谁负责。Deno 在第一个问题上越来越强,在第二个问题上始终不够好,第三个问题则取决于一家创业公司能活多久。技术选型从来不是单纯的性能比较,它是一次关于组织风险的下注。
▲ Ryan Dahl,Node.js 与 Deno 的创造者(图源:Cloudflare Blog)
兼容性是一条单行道
Deno 1.x 最初拒绝 npm。理由很合理:npm 的依赖树、私有 registry、node_modules 的嵌套结构,正是 Deno 想要摆脱的东西。但生态不是靠理由运转的。开发者要用的 gRPC、AWS SDK、Prisma、数据库驱动,大多只发布在 npm 上。没有这些包,Deno 就只能停在"玩具项目"的边界内。
2022 年,Deno 加入 npm: 说明符,允许直接导入 npm 包。2024 年 10 月,Deno 2 把兼容性推进到底:支持 package.json、node_modules、私有 npm registry、workspaces、monorepo,还引入了 LTS 发布通道。官方博客的说法很直接:重写整个 JavaScript 生态不现实,支持 Node 和 npm 是必要的。
于是出现了一个尴尬的问题。Deno 2 的官方 FAQ 里,有一条是记者和用户都会问的:"如果 Deno 完全向后兼容 Node,那为什么还要用 Deno,而不是 Node?"官方给出的答案是:Deno 有原生 TypeScript、Web 标准 API、完整工具链、默认安全,而且是一个没有外部依赖的单一可执行文件。这些答案都对,但它们都是"更好",不是"必须"。
▲ Deno 2 的发布视觉,主题是兼容 Node 与 npm(图源:Deno Blog)
兼容性是一条单行道。每增加一项 Node 兼容,Deno 与 Node 的差异就少一分;差异越少,迁移的理由就越弱。更麻烦的是,兼容并不等于无缝。Node 的生态里有大量隐含假设:原生模块、构建脚本、postinstall、运行时补丁、特定版本的 V8 行为。Deno 可以跑通大部分代码,但企业不会拿生产环境去赌那"大部分"。
2026 年,Ryan 在 Hacker News 上回复了一个问题:是谁决定放弃 Deno 运行时的?他的回答被 Brett Codes 完整引用:
It has been sucked into the gravity well of node compatibility, which forces it to behave exactly as Node does. Why reimplement Node? It works. Marginal performance or UX or security benefits are not enough.
这段话是整件事的题眼。它更像对路线终点的承认,而非失败的辩解:当一个替代品为了争取用户而不断兼容被替代者,它最终会失去自己的存在理由。Deno 的性能优势、权限模型、内置工具,都是真实的;但对大多数团队来说,这些优势加在一起,仍然抵不过一次运行时迁移的组织成本。
兼容的代价也不只是工程量。Deno 2 需要同时维护两套语义:一套是 Deno 原生的权限、模块和工具链,一套是 Node 的解析规则、原生模块和生命周期脚本。两套语义越靠近,维护成本越高;越分开,用户越困惑。Deno 2 的文档里,大量篇幅花在解释什么时候用 deno.json、什么时候用 package.json,以及哪些 npm 包在什么情况下不能直接用。这些细节对一个想迁移的团队来说,都是需要评估的风险。对一个已经在生产环境跑 Node 的团队来说,Deno 2 的兼容性解决了"能不能跑",却没有解决"为什么要跑"。
生态不是代码,是流动性
运行时的竞争,表面上是 API 和性能,底层是生态的流动性。
npm 官方口径是 1700 万开发者和 200 多万个包。这个数字的意义不在于"多",而在于"默认":库作者默认发布到 npm,教程默认用 npm,CI 默认装 npm,招聘要求默认写 npm。一个只有 11% 开发者使用的运行时,很难让库作者为它维护第二套构建、测试和文档。State of JavaScript 2025 的调查里,Node.js 在后端的使用率是 90%,Bun 是 21%,Deno 是 11%。Deno 官方首页写着 10 万 GitHub stars 和 40 万月活;这两个数字不小,但和"默认"之间还隔着一条河。
Deno 试图用 JSR 改变这条河。2024 年 3 月,JSR 公测:TypeScript-first、只支持 ESM、跨运行时、自动生成文档和类型声明。它甚至成立了一个独立治理委员会,成员包括 Vue 和 Vite 的创造者 Evan You,以及 npm 的创造者 Isaac Schlueter。这个姿态很明确:JSR 不想只做 Deno 的包仓库,它想做整个 JavaScript 生态的新注册表。
但注册表是典型的双边市场。没有包,开发者不来;没有开发者,包作者不来。npm 的规模本身就是它的护城河,而 JSR 能提供的差异化------TypeScript 原生、ESM-only、更好的文档------对大多数作者来说,还不足以构成"再维护一个发布流程"的理由。David Bushell 在 2026 年 3 月写道,开发者并不想替换 Node 和 npm,他们只是想要"已经有的东西,但更好用一点;一个没有摩擦的 drop-in 改进"。这句话解释了 JSR 的困境,也解释了 Deno 的困境。
JSR 的技术选择也值得看一眼。它只收 ESM,允许直接发布 TypeScript 源码,自动生成 .js 和 .d.ts,并用 provenance 做供应链证明。这些设计在今天看都很正确,甚至领先 npm 几年。但注册表的竞争不是功能竞争,而是网络效应竞争。一个包在 npm 上已经有可观的周下载量,作者没有动力为了 11% 的用户再维护一套发布流程;一个新手搜索框架,第一页仍然是 npm 的结果。JSR 可以做得更好,但它很难让人"先来这里"。
同样的错位出现在部署层。Deno Deploy 在 2021 年上线时,讲的是一个"代码推到边缘,全球低延迟"的故事。它一度覆盖 35 个区域。2025 年 5 月,Ryan 在《Reports of Deno's Demise Have Been Greatly Exaggerated》里承认,Deploy 的区域从 35 个缩减到 6 个。原因不复杂:大多数应用不是无状态函数,它们要连数据库,而数据库通常在一个区域;把计算撒到全球,并不能让查询变快,反而让冷启动和调试更麻烦。
这篇文章还承认,Deno KV 会停留在 beta,因为它不是通用数据库;Fresh 2 还在路上;公司会"继续投入"。到了 2026 年 3 月,Deno 的员工开始在社交媒体上集体告别。Deno 官网一度出现 404,David Bushell 截下了那张页面,页脚还写着"Powered by Deno Deploy"。
▲ 2026 年 3 月,deno.com 出现 404,页脚仍挂着 Deno Deploy(图源:David Bushell)
Deno 没有发布公开的裁员说明,也没有公布人数。外界能确认的只有员工公开离职这一事实。对一家已经成立五年的公司来说,这种沉默比任何解释都更能说明问题:它没有准备好一套"一切正常"的叙事。
产品线也在收缩。Fresh 在 2026 年年中被移入独立 GitHub 组织,此后公开更新很少;Deno Sandbox、Claw Patrol、celld 相继发布,方向从"更好的运行时"转向"更安全的 AI 代码执行"和"可自托管的分布式应用"。这些项目各自都合理,但放在一起看,更像是在寻找第二曲线,而不是在执行一条已经验证的主线。
Node 的慢变量
Deno 的失败很容易被写成"Node 赢了"。这个结论只对了一半。
Node 不是靠创新赢的。2014 年,因为治理分歧,Node 的核心维护者曾经分叉出 io.js;2015 年,io.js 合并回 Node,Node 4 发布,Node 基金会成立。那次分裂留下的教训被写进了后来的治理结构:技术决策公开,发布节奏固定,LTS 版本有明确的维护周期。Node 之后也会犯错,但它有一套能把反对者拉回桌面的机制。
这套机制的价值,在企业采用时会被放大。企业需要的不是一个更聪明的运行时,而是一个可以预测的运行时:什么时候发版,什么时候停止维护,出了安全问题谁负责,招人好不好招,出了事有没有商业支持。Node 的答案不性感,但很完整。
Node 还做了另一件事:把 Deno 的差异化一项项吸收。TypeScript 原生执行从 22.18 起不需要 flag,Node 24 把它带进 LTS,Node 26 将它稳定下来;内置测试运行器、watch 模式、fetch、权限模型、SQLite 支持,也都在最近几个大版本里陆续补齐。Node 26 在 2026 年 5 月发布,10 月 28 日进入 LTS,Temporal 默认开启。Deno 曾经用来证明"Node 太旧"的那些点,正在被 Node 一个个变成版本号。
这就是慢变量的力量。Node 不需要在发布会上赢,它只需要在每个 LTS 周期里,把用户最痛的那一项补上。Deno 每补一项兼容,Node 就少一个被替代的理由;Node 每补一项能力,Deno 就少一个差异化的卖点。
这套吸收策略并不戏剧化,却非常有效。Node 的发布周期是可预期的:大版本按年推进,LTS 有明确的维护窗口。企业采购、安全审计、招聘培训,都可以围绕这个节奏安排。Deno 的发布更快、功能更激进,但它的 LTS 只有六个月的回补窗口,公司的存续本身也成了变量。对一个 CTO 来说,选择哪一个,往往不是技术判断,而是风险管理。
另一面也值得记一笔。Deno 最大的遗产,可能不是它自己的用户,而是它逼着 Node 变得更好。没有 Deno 的权限模型和 TypeScript 原生支持,Node 的路线图未必会走得这么快。Deno 没有取代 Node,但它改变了 Node。
Node 也不是没有问题。node_modules 的体积、ESM 与 CommonJS 的割裂、工具链的碎片化,仍然没有根治。只是这些问题已经不足以让大多数团队换运行时------它们变成了"忍受",而不是"迁移"。下一个挑战者,更可能从部署模型、构建方式或 AI 代码执行这些层面出现,而不是再从"另一个运行时"开始。
Bun 的对照
同样是从 Node 手里抢用户,Bun 走了一条不同的路。
Bun 没有要求开发者重新学习一套模块系统。它选择做 Node 的 drop-in 替代:兼容 package.json、node_modules、Node 的核心 API,同时把包管理、打包、测试、运行时塞进一个二进制文件,用 Zig 重写,主打启动速度和安装速度。开发者迁移 Bun,通常只需要换一个命令,而不是换一套世界观。
这条路线的结果,写在 Anthropic 的收购公告里。2025 年 12 月,Anthropic 宣布收购 Bun,理由是 Claude Code 运行在 Bun 上,而 Claude Code 的年化收入已经达到 10 亿美元。Bun 官方当时公布的数字是月下载量 720 万,团队还有四年 runway。被收购后,Bun 继续保持 MIT 开源,继续做通用运行时。
Bun 的技术路线也更容易解释给团队听:它用 JavaScriptCore 而不是 V8,用 Zig 写底层,把包管理、打包、测试、运行时合成一个命令。对初创公司来说,这意味着更少的工具、更快的 CI、更小的镜像;对 Anthropic 来说,这意味着 Claude Code 可以作为一个单二进制分发,启动时间以毫秒计,不必依赖用户机器上的 Node 版本。收购不是对 Bun 的奖励,而是对一条已经跑通的分发链路的锁定。
把两笔交易放在一起看,差别很清楚。Anthropic 买 Bun,是因为 Bun 已经在自己的关键路径上:Claude Code 的分发、启动速度、单二进制交付,都依赖 Bun。买家有充分动机让 Bun 继续存在。Cloudflare 买 Deno,买的不是 Deno 运行时的未来,而是 Ryan、Bert 和 celld------一个能补上 workerd 自托管缺口的实现。Deno 运行时对 Cloudflare 的业务不是必需品,所以它可以进入维护模式。
这不是技术优劣的判决。Bun 的兼容路线更讨巧,但它的未来同样绑定在 Anthropic 的战略上;MIT 许可证给了社区一条退路,却不等于治理上的保险。Deno 的路线更理想主义,但它在商业上没有找到那个"非它不可"的买家。两家公司都拿了 VC,结局不同,差别不在于谁更"正确",而在于谁长在了别人的关键路径上。
Cloudflare 买的不是运行时
Cloudflare 的动机,在 Kenton Varda 的文章里写得比新闻稿清楚。
Cloudflare Workers 在 2017 年上线,Durable Objects 在 2020 年推出,workerd 在 2022 年开源。workerd 是 Workers 生产运行时的同一份代码,Apache 2.0 许可,任何人都可以拿它自托管。但 Kenton 承认,workerd 有一个长期缺口:它的 Durable Objects 只支持单实例,够本地测试,不够生产级扩展。Cloudflare 自己的分布式 DO 路由,依赖大量外部服务和一支 SRE 团队,不是一个自托管者想要的东西。他们一直想补,但一直没时间。
celld 正好补在这个缺口上。它是 Deno 团队在 2026 年 8 月发布的开源项目,用 Rust 写成一个二进制,对象存储是唯一的外部依赖,目标是让 Workers 和 Durable Objects 能在自己的基础设施上分布式运行。Kenton 说,看到 celld 时,Cloudflare 团队很高兴------这正是他们想做但没做出来的东西,而 Deno 团队替他们做出来了。
于是这笔交易的真实结构就清楚了。Cloudflare 拿到的是一支参与创造 Node、又创造了 Deno 的团队、一个可自托管的分布式 DO 实现、JSR 的基础设施、rusty_v8 的 V8 嵌入经验,以及一批正在寻找迁移目的地的 Deno Deploy 用户。它没有拿到 Deno 运行时的未来,因为它不需要。
Cloudflare 的 AI 叙事也需要这套原语。一个 agent 要调用工具、保存状态、维持 WebSocket、在失败后重试,最自然的落点是有名字、有存储、单线程执行的对象,而非无状态函数。Durable Objects 正好提供了这种"分布式单例加 SQLite"的组合;celld 则让这套模型不再只能跑在 Cloudflare 的网络里。对 Cloudflare 来说,这不只是补一个开源项目的缺口,而是把"agent 基础设施"从自家网络扩展到任何机房。
Kenton 还专门反驳了一个流行说法:Cloudflare 把 Workers 做得跟别的云不一样,是为了制造 lock-in。他的论证是,如果真是这样,Shopify 这类大客户根本不会签;workerd 开源、celld 可迁移,恰恰说明"开源和逃生通道是好生意"。这套论证是自洽的,也符合 Cloudflare 的利益:它想让 Workers 的编程模型成为默认,而不只是 Cloudflare 网络上的默认。自托管是打消"lock-in"恐惧的楔子,也是对抗 AWS、Vercel 这类平台的一种方式。对一个卖给开发者的平台来说,可信的退出机制本身就是获客成本的一部分。
但买方逻辑不等于社区保障。Cloudflare 的主营业务仍然是卖网络、卖平台;自托管能做到什么程度、以什么节奏推进,最终取决于它对自身收入的权衡。Deno 的结局已经证明,开源许可证挡不住一家公司在某个时刻改变优先级。代码可以 fork,生态和信任不能。
对一个 Node 开发者意味着什么
对 Node 开发者来说,这件事最容易被误读成"Node 又赢了"。更准确的说法是:运行时之争的战场换了。
Deno 输的不是 API 设计,也不是性能,而是"迁移"这件事本身。它要求开发者同时换运行时、换包管理、换部署平台,甚至换框架;而 Node 的生态已经把每一步都变成了默认。Bun 之所以能挤进来,是因为它把迁移成本压到了"换一个命令"。Cloudflare 之所以愿意买 Deno,是因为它看中的不是替代 Node,而是替代"应用必须部署在某个特定网络里"这件事。
这给 Node 开发者的启示,不是"不要用新东西",而是"看清楚一个新东西要求你换掉多少层"。如果一个工具只要求你换命令,它的采用曲线会快得多;如果它要求你换运行时、换 registry、换托管,那它需要的不只是更好的技术,还需要一个完整的迁移叙事和足够长的时间。对大多数团队来说,稳定比先进更重要;这句话在运行时选择上尤其成立。
平台风险也值得重新计价。Deno Deploy 在 2026 年初才转成正式可用,几个月后就宣布六个月后关停。对把业务放上去的团队来说,这更像一次被迫的基础设施重选,而不是普通的迁移。选择平台时,许可证只是第一层;维护者的收入结构、治理结构、退出历史,才是更硬的指标。
这不是说小平台不能选。小平台往往更快、更便宜、更愿意听用户说话。问题在于,选择小平台时,要把"退出成本"当成价格的一部分:数据能不能导出,API 是不是标准,运行时有没有替代实现,合同里有没有过渡期。Deno Deploy 给了六个月,这在商业上不算苛刻;但对一个已经把流量、构建、定时任务都放上去的团队来说,六个月只够做一次紧急迁移,不够做一次从容的架构调整。
至于"VC 资助的开源是否可靠",这件事提供的不是一个道德结论,而是一个结构观察。VC 是一种带到期日的资金:它要求回报,要求退出。把它用在需要十年维护的基础设施上,就必须提前设计"退出之后谁来维护"。Deno 拿了 2600 万美元,做出了一个被广泛使用的运行时,最终以团队并入的方式退出;代码留下来了,运行时没有。Bun 也拿了 VC,但它在一个关键时间点长进了 Anthropic 的关键路径,于是买家有动机让运行时继续。差别不在"VC 是好是坏",而在"退出时,买家买的到底是什么"。
这不是说 VC 项目注定失败。Deno 的代码、JSR 的治理尝试、celld 的设计,都是真实的成果;没有那 2600 万美元,这些成果可能根本不会出现。问题在于,VC 的回报模型要求一个明确的退出事件,而开源基础设施的价值往往体现在"长期存在"而不是"被谁买下"。当两件事冲突时,退出事件会优先。Deno 的运行时不是被竞争对手杀死的,它是在一次合理的资本退出里,被放在了优先级较低的位置。
同样的分析也适用于基金会和公司主导的项目。Node 由 OpenJS 基金会治理,稳定,但决策慢;Go、TypeScript 由大公司主导,资源足,但路线图受公司战略影响;Rust 有基金会,也要面对资金和维护者 burnout。没有一种模式天然免疫。真正要问的是三个问题:谁为日常维护付钱,谁能否决路线图,如果核心团队离开,代码和社区能不能继续。
对普通开发者来说,能做的很有限,但并非没有:尽量把业务逻辑放在标准 API 上,别把核心能力绑在某一家的独家 binding 上;在选平台时,把"如果它明天被收购或关停,团队怎么走"写进架构决策;对"开源"保持精确------许可证、治理、维护者,是三件不同的事。
结尾
2009 年那场 IRC 演示里,Ryan 反复提到一个问题:一台服务器、一个线程,能撑住多少连接。Node 用异步 I/O 回答了它;Deno 用新的运行时和工具链回答了它;celld 和 Durable Objects 则把问题推进到"如果一台机器不够,应用能不能从设计上就分散到多台机器"。
Deno 的八年,像一次成功的失败。它没有成为 Node 的替代品,但它把权限模型、TypeScript 原生、Web 标准、内置工具链这些想法,推进了 Node 的路线图,也把自己剩余的价值,交给了 Cloudflare 的下一层抽象。运行时可以停止开发,抽象不会。真正留下来的,不是 deno 这个命令,而是它迫使整个生态回答的那些问题。
接下来值得看的,不是 Deno 会不会"复活",而是三件更具体的事:Cloudflare 会把 workerd 的自托管做到什么程度,JSR 在没有 Deno 运行时之后还能不能独立生长,以及 Node 的下一个对手,会不会根本不再是一个运行时。
本文部分内容由 AI 辅助生成,并经人工核对与润色;文中数据与引语均来自公开报道,见文末引用资料。
欢迎关注同名公众号:此方的手账
不止技术。科技新闻解析、编程语言史、大厂史、世界简史正在连载中。希望成为让你了解一些奇怪知识的电子榨菜和厕所读物。