谢谢你,Deno
摘要
Deno 正加入 Cloudflare,并逐步缩减对其运行时的投入;与此同时,JSR 将继续在 Cloudflare 的基础设施上运行,团队也将把 celld 合并到 workerd 中。文章回顾了 Deno 带来的竞争如何推动 Node/npm 生态系统的改进,尽管 Deno 自身始终未能形成足够的用户规模。
暂无内容
查看缓存全文
缓存时间:
2026/10/16 04:16
# 谢谢你,Deno | vlt /vōlt/
来源:https://www.vlt.io/blog/competition-keeps-javascript-moving
所有文章 (https://www.vlt.io/blog)
开源注册表
Deno 正在加入 Cloudflare,并逐步减少对其运行时的投入。它的存在让我们所有人都受益了。
一张黑白照片,铁轨延伸向远山上方低悬的太阳
Ryan Dahl 上周宣布 (https://deno.com/blog/cloudflare),Deno 团队将加入 Cloudflare。Deno 运行时将在未来一年逐步停止开发,JSR (https://jsr.io/) 将继续运行在 Cloudflare 的基础设施上,而根据 Cloudflare 的文章 (https://blog.cloudflare.com/deno-joins-cloudflare/),该团队的新任务是将 Deno 的 celld (https://celld.dev/) 合并到 workerd (https://github.com/cloudflare/workerd) 中。
这一消息公布的当天,恰好是 Deno 2 发布两周年。Bun 则在十个月前加入了 Anthropic (https://bun.com/blog/bun-joins-anthropic)。人们很容易由此得出结论:替代运行时的实验已经结束,Node 不战而胜。实际上,生态系统已经获得了 Deno 所推动的那些好处,只是并非来自 Deno 本身。
## 竞争是健康生态系统的必要条件
遗憾的是,Deno 在生产环境中始终未能真正达到足够的普及规模;Node 在 2026 年的主导地位,与 2018 年一样稳固。Deno 真正做到的,是让占据主导地位的 Node 重焕活力,并向其施加压力,而且这种压力并非单向流动。
Deno 一开始选择了彻底另起炉灶。Ryan 在 2018 年的 JSConf EU (https://www.youtube.com/watch?v=M3BM9TB-8yA) 上登台,列举了他会采取哪些不同于 Node 的做法:默认拒绝的权限机制、将 TypeScript 作为一等输入、在服务器上使用 Web 标准 API、仅支持 ES 模块,以及单一可执行文件。尤其鲜明的是,不要 npm,不要 package\.json,也不要 node\_modules。依赖就是 URL。演示文稿 (https://tinyclouds.org/jsconf2018.pdf) 说得很直白:“无需列出依赖。”
我们中许多在 npm 和 Node 上投入多年的人,都对最后这一点持怀疑态度(不是权限机制或 TypeScript,这两点显然很好),当时也公开表达了看法。我们以前就经历过这种情况:在盗链盛行的年代,每个网页都从别人的服务器加载 jquery\.min\.js,一旦文件被移动或遭到篡改,网页就会出问题。URL 告诉你某个东西曾经在哪里,而不是它究竟是什么。一旦你开始在意交付的字节是否与测试过的字节完全相同,就需要完整性哈希,以及一个记录它的地方,于是你又重新发明了锁文件。Node 技术指导委员会的 Matteo Collina 在 2020 年表示 (https://www.infoq.com/articles/fastify-nodejs-web-framework-interview/):“另一起 left-pad 事件随时可能发生,但这次不会有一个能解决问题的‘中心机构’。”其中一些怀疑带有防御心态,但最终事实证明,这些怀疑恰好是对的。
Deno 1\.0 于 2020 年按照最初的设想发布,随后四年却在逐项收回这些主张。首先是 deps\.ts 约定,用一个文件重新导出所有 URL:这实际上就是一份清单,只是名字不同。接着是 lock\.json,为每个 URL 记录一个完整性哈希:这就是锁文件。再后来是导入映射,让你又能使用裸模块说明符。如今,Deno 自己的文档 (https://docs.deno.com/runtime/packages/) 建议优先使用注册表,而不是 HTTPS 导入,因为后者“可能在不同文件中漂移到不同版本”,并且“信任提供内容的主机”。这正是 2018 年那些反对意见,只不过现在被重新表述为使用指南。
然后 Bun 出现了。Bun 0\.1 (https://github.com/oven-sh/bun/releases/tag/bun-v0.1.0) 于 2022 年 7 月发布,押注的方向恰好相反:为了速度从头重建工具链,但运行现有 npm 包、读取 package\.json,并充当 node 的直接替代品。大约六周后,Deno 发布了《Deno 即将迎来重大变化》 (https://deno.com/blog/changes),宣布引入 npm: 说明符,承诺在三个月内让 80–90% 的 npm 包能够运行,并提出成为“最快的 JavaScript 运行时”这一新目标。Deno 将这次转向归因于用户反馈;从时间上看,Bun 很可能也是重要原因。2024 年 10 月发布的 Deno 2 (https://deno.com/blog/v2.0) 通过全面兼容 Node 和 npm,完成了这一转变。作为 Node 生态系统的替代方案推出四年后,Deno 成了运行这个生态系统的另一种方式。
这是正确的选择,同时也承认了一个事实:生态系统不会在一夜之间抛弃十多年积累的依赖。Cloudflare 于 2022 年开源的 workerd (https://blog.cloudflare.com/workerd-open-source-workers-runtime/) 也出于同样的原因发展出了自己的 Node 兼容层:包都在那里。
Node 最终也不得不作出回应。自 2018 年以来,它陆续推出了全局 fetch (https://nodejs.org/en/blog/announcements/v18-release-announce)、WebSocket、Web Streams 和 Web Crypto;稳定的测试运行器 (https://nodejs.org/en/blog/announcements/v20-release-announce) 和 \-\-watch;\-\-env\-file (https://nodejs.org/api/cli.html#--env-fileconfig) 和单一可执行文件构建;稳定的权限模型 (https://nodejs.org/api/permissions.html);默认开启的类型剥离 (https://nodejs.org/api/typescript.html);node:sqlite (https://nodejs.org/api/sqlite.html);以及 require\(esm\)。Node 的贡献者们(其中许多是志愿者)付出了艰苦努力,倾听反馈并作出重大改变,他们值得高度赞扬。但我认为,如果没有另外三个运行时率先实现其中许多想法,这些变化就不会按这样的时间表发生。成熟的开源项目很少缺乏好点子。它缺的是紧迫感,而竞争者提供了这种紧迫感。
标准化工作也源于同样的压力:WinterCG (https://wintercg.org/) 于 2022 年成立,因为几个颇具实力的运行时让“最小公共 API 是什么?”成了一个实际问题。如今,它已成为 Ecma TC55 (https://wintertc.org/),无论接下来哪些运行时发生整合,它都应该能继续存在。
## 包管理器与注册表
在 JavaScript 包生态系统历史的大部分时间里,它都是一种单一格局:一个客户端、一个注册表,以及一套不够正式的 API 契约,以至于十五年来它实际上一直没有文档 (https://www.vlt.io/blog/the-massive-hole-in-the-npm-ecosystem)。此后几乎每一次改进,都源于有人不愿接受现状。
Yarn(2016 年)坚持安装结果应当具有确定性,为我们带来了锁文件、工作区和离线缓存;npm 5 在次年推出了 package\-lock\.json。pnpm 证明了 node\_modules 不必由数百兆字节的重复文件组成。Bun 让 install 快到迫使既有工具重新审视自身性能。Deno 主张,你应该能够在引入依赖之前阅读其源代码;虽然 URL 导入没有坚持下来,但这个理念保留了下来。
最近最鲜明的例子就是安装脚本。pnpm 和 Bun 不再默认运行它们;vlt 从一开始就没有默认运行过 (https://www.vlt.io/blog/vlt-build)。我在 npm 工作的整个期间,内部一直有人提出这一主张,却始终没有成为默认行为。今年 6 月,在一连串供应链蠕虫事件之后,GitHub 宣布 npm 12 也将不再默认运行它们 (https://www.vlt.io/blog/npm-12-breaking-changes)。这些年来,这个想法本身没有变化;只是足够多的其他包管理器已经实现了它,npm 再也无法将其视为激进之举。压力同样双向流动:我们从 pnpm 借鉴了 catalogs (https://www.vlt.io/blog/centralized-dependency-management-made-simple),而 pnpm 的 namedRegistries (https://pnpm.io/settings/dependency-resolution#namedregistries) 则借鉴了我们的具名注册表别名。
在注册表方面,JSR (https://deno.com/blog/jsr_open_beta) 值得肯定。它所作的选择与我们不同:发布 TypeScript 源代码、强制使用 ESM、从代码生成文档。我们对其中一些做法并不认同,但还是为 vlt 添加了 jsr: 支持 (https://www.vlt.io/blog/jsr-support),因为用户提出了这个需求。它得以在此次逐步收尾中继续存在,据我所知,是因为它运行成本低、API 有文档,而且 Cloudflare 有理由让它继续运转。
## 现在会发生什么变化
如今,最受欢迎的两个独立、获得风险投资支持的 JavaScript 运行时,都归入了主营业务另有所属的公司。Jarred Sumner 表示 (https://bun.com/blog/bun-joins-anthropic#frequently-asked-questions),Bun 团队与 Claude Code 团队的关系“可能会类似于 Google Chrome <\> V8 之间的关系”,但拥有更多独立性;而 Cloudflare 的文章明确表明,workerd 的路线图就是 Cloudflare 的路线图。JavaScriptCore 和 V8 一直都是这样获得资助的,但这依然是一种变化。
Deno 运行时是否会出现社区分支,将告诉我们:生态系统是否足够重视一个默认安全、标准优先的运行时,愿意为一个不依附于云平台的运行时买单。而将 celld 合并到 workerd,则为一个长期缺少选择的层面带来了新选项:由 Ryan 和 Bert Belder 领导的、可自行托管的 Workers 和 Durable Objects 开放实现。
JavaScript 几乎在每一层都有保障:三个用于生产环境的引擎、多个运行时、多个包管理器。当某一层发生整合,就像运行时层现在这样,其他层仍能支撑整个体系。让这一切成为可能的频繁变动,也恰恰是人们抱怨最多的东西。“JavaScript 疲劳”十年来一直是个老梗:每周一个新框架,每月一个新打包工具,还有又一个包管理器——是的,我知道自己也参与了这件事。但没有人必须离开 Node,才能获得 fetch、权限模型,或无需构建步骤的 TypeScript;如今,也没有人必须更换包管理器,才能让安装脚本默认关闭。这些功能之所以出现在人们原本就在使用的工具里,是因为其他人率先实现了它们,而占据主导地位的工具不得不回应。项目未必总能获胜,但理念通常能,而最终用户无论如何都收获了这些成果。
致 Ryan、Bert、Bartek,以及 Deno 团队所有过去和现在的成员:你们共同付出的努力,让我们共享的生态系统更加丰富。**谢谢你们!**
**Darcy Clarke** vlt 创始人兼首席执行官
相似文章
Simon Willison's Blog
Cloudflare 正在收购 Deno,基于其 celld 项目进行构建,并将 workerd 的自托管作为一等功能;而 Deno 运行时在此后一年内只会获得错误修复,随后开发将终止。Deno 和 Node.js 的创造者 Ryan Dahl 认可了这一决定,他表示 Deno 已被 Node 兼容性所拖累,而他希望专注于 celld 这类基于对象存储的服务器模型等新抽象。
X AI KOLs Timeline
Cloudflare 正在吸纳 Deno 核心团队成员,包括 Ryan Dahl 以及 Bartek Iwańczuk 的同事,以将 workerd 打造为一流的、可自托管的开源 JavaScript 运行时,这标志着 JavaScript 运行时格局的一次显著转变。
Lobsters Hottest
Deno 宣布整个团队加入 Cloudflare:Deno 运行时将在一年维护期后停止开发,Deno Deploy 六个月后关闭,JSR 将迁移至 Cloudflare 基础设施,未来开发重心转向基于 Cloudflare Workers 和 Durable Objects 的统一平台(celld)。
X AI KOLs Following
Deno 团队及其创始人 Ryan Dahl 将加入 Cloudflare,以改进 Workers 对 Node.js 开发者的支持,并推动 workerd 成为核心运行时原语。
Lobsters Hottest
一篇反思性文章,批评 Deno 转向与 Node.js 兼容的做法,认为这削弱了其原本简洁、零配置的理念,而正是这些特点让开发者对其青睐有加。