Deno 官宣一年后停更:我把它的招牌特性在 Node 26 和 Bun 里挨个找了一遍

10 月 9 号周五,Deno 官博发了一篇 Ryan Dahl 署名的公告,标题看着像好消息:Deno 团队整体加入 Cloudflare。真正的条款藏在正文里------Deno runtime 只再维护一年,按月发 bugfix 和安全更新,之后官方停止开发,代码保持开源,欢迎社区接手;Deno Deploy 只剩六个月,之后关停;JSR 继续运营,基础设施搬进 Cloudflare;rusty_v8 继续支持,往后要整合进 workerd。

这帖子在 Hacker News 上冲到 1234 分、668 条评论,周六我点进去的时候,前排吵成一团。有人贴了一句挺扎心的总结:"这不是收购,是 acquihire,runtime 被顺手关掉了。"还有人已经在喊 fork 出 opendeno。但喊归喊,代码层面的现实是:一年后没有官方维护的 Deno 了。

我手头有几个用 Deno 写的小工具,都是自用性质,扔了可惜、不迁又不踏实。与其跟着热搜焦虑,不如花点时间搞清楚一个具体问题:Deno 这几年真正攒下的东西,在 Node 26 和 Bun 里能不能找到下家。于是今天把三个运行时各装了一份------Deno 2.9.7、Bun 1.4.3(10 月 10 号刚发的)、Node 26.11.1------用同一段短链服务的逻辑各写了一版,逐项对照。

先说不意外的那部分

代码迁移本身比我预想的顺。我的短链服务用了三个 Deno API:Deno.serve、Deno.openKv、Deno.env。换成 Node 就是 node:http 加 22.5 之后内置的 node:sqlite,换成 Bun 就是 Bun.serve 加 bun:sqlite,两边都不用装任何 npm 包。三个版本各 40 来行,功能完全对齐:PUT 写入、GET 302 跳转、列表统计,全通。 顺到什么程度呢,顺到我一开始以为这篇文章写不出东西了。

第一个意外发生在写 Deno 版的时候。我下意识认为 Deno 2.x 的 KV 早就转正了,结果一跑就撞墙:

vbnet 复制代码
error: Uncaught (in promise) TypeError: Deno.openKv is not a function
    at file:///root/deno-exp/app/main.ts:2:23

info: Deno.openKv() is an unstable API.
hint: Run again with `--unstable-kv` flag to enable this API.

到 2.9.7 为止,Deno.openKv 还挂在 unstable 门后面,得显式加 --unstable-kv。我印象里这 API 稳定好几年了,看来印象是错的,文档没骗我,是我自己想当然。这条顺带提醒一下还在 KV 上的项目:连 Deno 自己都没敢把这个门拆掉。

真正的差距在权限这页

权限模型是 Deno 这些年最招牌的差异化:默认什么都干不了,干什么是你显式批的。我特意做了一个"不传权限"的启动对照,这一页测出来的差距比我想的大。 Deno 这边,deno run main.ts(不带任何 allow)直接死在第 3 行:

vbnet 复制代码
error: Uncaught (in promise) NotCapable: Requires env access to "PORT",
run again with the --allow-env flag

报错粒度细到具体变量名,还顺手告诉你该补哪个 flag。补上 --allow-net --allow-env --unstable-kv 再跑,服务起来,全部功能正常。 Node 26 这边有意思了。我一直有个旧印象:Node 的 permission model 只管文件和子进程,网络是裸奔的。实测发现这个印象也过时了------node --permission main-node.mjs,无任何放行 flag,服务死在监听那一步:

vbnet 复制代码
Error: Access to this API has been restricted. Use --allow-net to manage permissions.

Node 26 的权限模型把网络也管上了。但两个"但是"得说清楚。第一个,--allow-net 加上之后启动会打一行警告:

lua 复制代码
ExperimentalWarning: The flag --allow-net is under experimental phase.

管网络这件事在 Node 这里还是实验性 flag,没转正。第二个更要命:--permission 模式下,我代码里那句 process.env.PORT 照读不误,一个字的警告都没有。环境变量在 Node 的权限模型里默认放行,而读环境变量恰恰是最常见的密钥泄露入口。

Bun 就更干脆了。我在 bun --help 和 bun run --help 里翻了一圈,permission、allow 相关的选项一个都没有。1.4.3 这个昨天刚发的版本,权限模型这个概念在 Bun 里不存在------不是不完善,是没有。

对照下来这页很清楚:Deno 的默认全拒+细粒度报错,Node 用一个实验性 flag 追到了网络监听,env 仍然不设防,Bun 没参赛。这部分能力迁移过去,等于降级。

单文件分发:一快一慢一个坑

短链服务这种小工具,我历来喜欢编成单个可执行文件扔服务器上。三个运行时在这件事上的画风差异,是这次实测里数据最硬的部分。 Deno 和 Bun 都是一条命令的事:

css 复制代码
deno compile --allow-net --allow-env --unstable-kv -o link-deno main.ts
bun build --compile main-bun.ts --outfile link-bun
产物 大小 耗时
deno compile 104.6 MB 26.4 s
bun build --compile 90.8 MB 0.158 s
node SEA(CJS) 150.1 MB 4 步流程 + 5.8 s 注入

Bun 那个 0.158 秒我盯着看了好几秒------比 Deno 快了一百多倍,产物还小 14 MB。Deno 的 26 秒在 1 核 2G 的沙盒里跑得我心焦,不过好在是一次性成本。 Node 的 SEA 就不是"命令"了,是"流程":先写一个 sea-config.json,跑 node --experimental-sea-config 生成 blob,把 node 二进制复制一份,最后拿第三方工具 postject 往里注入。四步走完,还埋着一个坑------我最初的版本用 ESM 主脚本(main-node.mjs),注入成功,运行直接趴窝:

vbnet 复制代码
Warning: Failed to load the ES module: main-node.mjs.
Make sure to set "type": "module" in the nearest package.json file

提示让我设 "type": "module",设了没用,这是 SEA 对 ESM 的支持问题,不是配置问题。改成 CommonJS 版本重新走一遍流程才跑通。到 Node 26 为止,官方文档里 SEA 仍标着实验性,ESM 支持就是没做好。150 MB 的产物里躺着一份 CJS 兼容版,这事本身就很 2020。

三个产物我都在沙盒里拉起来验过:Deno 和 Bun 的二进制开箱即用,Node 的 CJS 版也正常,PUT 写入、302 跳转全部对得上。

账算下来,真正要迁的只有一处

逐项对完,情况比热搜氛围好不少。HTTP 服务、SQLite 存储、TypeScript 开箱(Node 26 现在连 type stripping 都默认开了,纯类型标注的 .ts 文件直接 node plain.ts 就能跑)、单文件分发,这些 Deno 日常使用的部分,Node 和 Bun 都有像样的下家,多数还不用装包。

真损失集中在两块。一块是权限模型,前面说透了,没有平替。另一块是内置工具链:deno fmt 和 deno lint 我顺手跑过,零配置直接工作,换成 Node 就得自己拼 prettier 加 eslint 的配置文件,Bun 有内置 test 但没有 fmt 和 lint。这类东西单看不痛,摊开来全是琐碎的重建成本。

我的决定是想清楚了再走:Deploy 上有东西的,六个月死线,别赌,早迁;跑在自己服务器上的 runtime 项目,不急着动------一年维护期里安全更新照发,先用着,同时把新东西往 Node 或 Bun 上写。权限模型这块等 Node 那个实验性的 --allow-net 转正再说,转正之前,我对它的态度跟对 Bun 一样:不能依赖。

至于 Deno 本身,开源项目死透的先例不多,社区接手的先例也不多,一年后是什么样,今天谁说了都不算。就写到这吧,等官方下个月的月度更新出来,我再看一眼有没有新的说法。

相关推荐
七牛开发者6 小时前
从 Bun 到 Deno,AI 时代的开发工具正在经历什么?
agent·deno·bun
孟陬8 小时前
Node.js 中 `\b` 的作用
node.js·bun
小小荧12 小时前
🚀 Node.js 之父离开 Deno,带着整个团队加入了 Cloudflare
前端·node.js
damoluomu13 小时前
Directus 换掉 GPL 之后,Node.js CMS 到底怎么选?(四)
node.js
前端一小卒14 小时前
搜索 API 额度用完返回空数组,Agent 就开始一本正经地胡说
前端·javascript·node.js
濮水大叔1 天前
Cabloy 双引擎架构详解:Vona 与 Zova 是如何协作的
typescript·node.js·全栈
LRL_1 天前
跨平台 Node 模块安装指南:如何利用 pnpm/npm 配置`supportedArchitectures` 锁定平台依赖
前端·npm·node.js
逍遥5966070101 天前
网络设备交换机路由器 AI 配置助手
node.js·硬件工程
damoluomu2 天前
Directus 换掉 GPL 之后,Node.js CMS 到底怎么选?(三)
node.js