🦕 Deno

一句话定性

2020 年,Ryan Dahl 站到台上,列出他对 Node.js 的十个遗憾,然后说:“所以我做了 Deno。” 这是技术史上罕见的一幕——原作者亲手否定自己最成功的作品,从零重写一个”如果当年知道现在所知,会怎么做”的运行时。


一、它是什么 & 出现的时代

Deno 是一个基于 V8、用 Rust 编写的 JavaScript / TypeScript 运行时,2020 年由 Node.js 之父 Ryan Dahl 发布(1.0 版)。

它的起点是 Dahl 2018 年在 JSConf EU 的著名演讲 《10 Things I Regret About Node.js》(我对 Node 的十个遗憾)。Deno 就是这场演讲的”工程化答案”。

Deno 名字的由来

Deno = De + No(de),把 “node” 的字母重排。它的吉祥物是只恐龙(dino),致敬 JS 的”史前”气质。


二、为什么会出现(解决上一代什么痛点)

Ryan Dahl 列出的”十个遗憾”(节选最关键的几条),每一条都直接对应 Deno 的一个设计:

Node 的遗憾Deno 的修正
没坚持用 Promise(导致回调地狱)全面 async/await + Web 标准 API
安全模型缺失(脚本默认全权限)默认沙箱,文件/网络/环境需显式授权
构建系统(GYP)选错了用 Rust + 标准工具,无 node-gyp
package.json / node_modules 设计臃肿去掉两者,改用 URL 导入 + 全局缓存
模块解析太复杂(隐式扩展名、index.js)显式、像浏览器一样的 ES-Modules
没有原生 TypeScript原生执行 TS,无需配置

核心矛盾

Node 诞生于 2009,当时 Promise/ESM/TS 都还不成熟,很多决策是”时代的妥协”。十年后这些妥协变成了包袱——而 Dahl 想要一张白纸,直接采用今天的 Web 标准。


三、核心机制 & 为什么流行

1. 默认安全(Secure by Default)

Deno 脚本默认跑在沙箱里,不能读文件、不能联网、不能读环境变量,除非你显式授权:

deno run app.ts                    # 啥都不能干
deno run --allow-net app.ts        # 只允许联网
deno run --allow-read=./data app.ts # 只允许读 ./data

这直接针对 Node 的供应链攻击温床——一个恶意依赖再也不能”装上就偷你的密钥”。

2. 原生 TypeScript

deno run app.ts 直接跑,不需要 tsc、不需要 ts-node、不需要配置。TS 是一等公民。

3. Web 标准 API

fetchRequestResponseURLWeb CryptoWorker……Deno 直接复用浏览器里你已经会的 API,而不是 Node 那套自创的 http/Buffer。理念:浏览器和服务端不该是两套知识。

4. URL 导入 + 去 node_modules

import { serve } from "https://deno.land/std/http/server.ts";

模块直接从 URL 引入,首次下载后缓存到全局——没有 node_modules、没有 package.json(早期理念)。像浏览器一样去中心化。

一体化工具

Deno 内置 formatter(deno fmt)、linter(deno lint)、test runner(deno test)、打包、文档生成——开箱即用,无需拼装工具链。这点后来被 Bun 进一步发扬。


四、带来的新问题 / 副作用

理想主义撞上生态惯性

  1. 生态不兼容是致命伤:早期 Deno 拒绝 npm / node_modules,意味着几十万个 npm 包用不了。开发者无法迁移,推广严重受阻。这是 Deno 最大的战略失误——低估了生态惯性(二阶效应)
  2. URL 导入的隐患:依赖散落在各种 URL,版本管理、安全审计、离线可用性都成问题,后来不得不引入 deno.json 和 import maps 来收敛。
  3. “更好的设计”未必赢:Deno 几乎每个技术决策都比 Node 更”正确”,但正确 ≠ 流行。VHS 战胜 Betamax 的故事在重演。

五、现状 / 演化

  • Deno 2(2024)的战略转向:全面拥抱 npm 兼容package.json,从”Node 杀手”改口为”更好的 Node 开发体验”。这是对生态惯性的低头,也是务实的胜利。
  • 主打场景:边缘计算(Deno Deploy)、一体化开发体验、安全敏感场景。
  • 推出 JSR(JavaScript Registry),一个面向 ESM/TS 的现代包仓库,挑战 npm。
  • 它的很多理念已被”反向移植”回 Node.js(原生 ESM、内置 test、--strip-types)——即使 Deno 没赢,它的思想也赢了

六、对后续技术的影响(因果链)

        Node.js 的"十个遗憾"(Ryan Dahl 自我反思)
                       │
                       ▼
                 Deno(2020, Rust)
                       │
   ┌───────────────────┼─────────────────────┬──────────────────┐
   ▼                   ▼                     ▼                  ▼
 默认安全沙箱        原生 [[TypeScript]]   Web 标准 API        去 node_modules
   │                   │                     │                  (URL 导入)
   │                   │                     │                  │
   │                   ▼                     ▼                  ▼
   │           倒逼 Node 补 --strip-types   推动 WinterCG       生态惯性反噬
   │                                       (运行时标准对齐)     │
   ▼                                                            ▼
 影响 [[Bun]] 也走"安全/标准/一体化"路线          Deno 2 妥协,转向 npm 兼容

历史地位

Deno 是一封写给整个 JS 生态的”检讨信 + 提案书”。它在商业上没能颠覆 Node.js,却在思想上重塑了所有运行时——默认安全、原生 TS、Web 标准对齐,如今都成了行业共识。它证明了一件事:有时候推动进步的不是取代王者,而是逼王者变得更好。


🔗 相关:JS运行时演进史 | Node.js | Bun | TypeScript | ES-Modules | Chrome | npm-Yarn-pnpm-包管理