我为什么差点放弃 Deno——但又回来了

Tokio 事件循环:比 Node.js 更快?真相有点复杂
Deno 底层用的是 Rust 写的,异步运行时则是 tokio。Node.js 是 libuv。两者最大的区别——libuv 是单线程事件循环配线程池,而 tokio 是多线程 work-stealing 调度器。简单类比:libuv 像一个餐厅,一个服务员(事件循环)负责点单,然后把耗时活交给后厨(线程池);tokio 则是多个服务员同时点单,还能互相偷对方手上的活儿——这样就不会有人闲着。
权限模型:安全是好事,但用起来能气死人
Deno 最引以为傲的,可能就是它的安全沙箱了。默认情况下,Deno 程序没有任何文件、网络、环境变量权限——除非你明确授权。这个设计初衷很好,尤其对于运行第三方脚本,你再也不用担心 `rm -rf /` 了。可在实际开发中,权限变成了一个“狼来了”式的累赘。比如你写个简单的 CLI 工具,需要读文件、写文件、请求网络,启动时要加一串长长的 `–allow-read –allow-write –allow-net=api.example.com`…… 每次敲命令都像在念咒语。最抓狂的一次,我在 CI 里跑测试,忘了加 `–allow-env`,结果全都因为读不到环境变量挂掉,排查了半天。
兼容 npm 的坑:你以为无缝,其实一地鸡毛
Deno 从 1.28 开始支持 npm 包,这绝对是大动作。我也兴冲冲地迁移了一个小项目,结果踩坑无数。首先,很多 npm 包依赖 Node.js 的内置模块,Deno 虽然做了 polyfill,但仍然存在不兼容。比如 `fs` 模块的某些方法行为不一致,`child_process` 彻底不能用(Deno 用自己的方式)。第二,有些包在 `node_modules` 里做了一些黑魔法,比如动态 require,到了 Deno 的 ESM 世界直接挂掉。最典型的就是 `jest`——你没法在 Deno 里跑 Jest 测试,除非用 `deno test` 原生支持。第三,类型定义更是一团糟,npm 的声明文件很多是为 Node 环境写的,全局变量冲突严重。 所以,my 建议:别幻想把 Node 项目直接搬到 Deno。最好是新项目从零用 Deno,或者逐步替换那些纯逻辑、不依赖底层系统的模块。对于必须使用 Node 包的场景,可以考虑用 Deno 的 `–compat` 模式,但它的本质是模拟 Node 环境,稳定性和性能都打折扣,只适合过渡阶段。事件循环与 V8 隔离:不止是加个壳
