Node.js 的十个遗憾
2018 年柏林 JSConf EU,Ryan Dahl 站上讲台,发表了让整个 JavaScript 社区震惊的演讲:《我对 Node.js 感到遗憾的 10 件事》。作为 Node.js 的亲手创建者,他列举了自己认为当年犯下的设计错误:
- 不坚持 Promise:Node.js 早期加入了 Promise,但后来退出了,导致 callback 地狱盛行多年
- 安全性被忽视:程序一旦运行,就能访问文件系统、网络、环境变量,没有任何沙盒保护
- build 系统 GYP:为 native 扩展选择了错误的构建工具,后来引发大量兼容性问题
- package.json 与 node_modules:中心化注册表(npm)、庞大的 node_modules 目录,制造了依赖地狱
- 没有扩展名的 require:
require('foo')不够明确,模块系统设计不够清晰 - index.js 的特殊意义:不必要的复杂化
演讲结尾,他宣布:"我正在开发 Deno。"
Deno 的名字:Deno 是 Node 的字母重新排列("De-no")。恐龙(Dino)是 Deno 的吉祥物,代表着"上个时代的 Node"。官方 logo 是一只可爱的恐龙,完整体现了这个致敬与超越的精神。
Deno 1.x → 2.0 重大变化
Deno 1.0 于 2020 年发布,虽然理念先进,但缺乏 npm 生态兼容性,被很多人认为"不实用"。2024 年发布的 Deno 2 彻底改变了这一局面:
| 特性 | Deno 1.x | Deno 2.0 |
|---|---|---|
| npm 包兼容 | 实验性,不稳定 | 完整支持,绝大多数 npm 包可用 |
| node: 协议 | 部分支持 | 完整支持,import fs from 'node:fs' |
| Workspace | 不支持 | 支持,多包 monorepo 管理 |
| package.json | 不支持 | 支持读取,与 npm 项目互操作 |
| JSR 包注册表 | 无 | 官方支持,jsr: 前缀导入 |
| 标准库 | URL 直接导入 | @std/* 命名空间,稳定版本化 |
| Deno KV | 实验性 | 稳定,生产可用 |
| V8 版本 | 旧版 | 持续跟进最新 V8 |
Deno 2 的战略意义:通过完整的 npm 兼容性,Deno 2 终于能够使用 npm 生态的数百万个包,同时保持自己安全沙盒、原生 TypeScript 的核心优势。这是 Deno 从"理想主义实验品"到"生产级可选项"的关键跨越。
与 Node.js / Bun 三方对比
| 维度 | Node.js 22 | Bun 1.x | Deno 2 |
|---|---|---|---|
| JS 引擎 | V8 | JavaScriptCore | V8 |
| 原生 TypeScript | 实验性(--strip-types) | 内置(类型擦除) | 内置(类型擦除) |
| 安全沙盒 | 无 | 无 | 默认沙盒,需显式授权 |
| Web API 兼容 | 部分 | 部分 | 最完整(最接近浏览器) |
| npm 兼容 | 完整 | 完整 | 完整(npm: 前缀) |
| 内置工具链 | 最少 | 多(fmt/test/bundle) | 最完整(fmt/lint/test/doc/compile) |
| 包注册表 | npm | npm | JSR + npm |
| HTTP 性能 | ~65k req/s | ~120k req/s | ~78k req/s |
| 内置 KV 存储 | 无 | 无 | Deno KV(SQLite+云) |
| 边缘部署平台 | 无官方 | 无官方 | Deno Deploy(官方) |
安装 Deno
macOS / Linux
# 官方安装脚本
curl -fsSL https://deno.land/install.sh | sh
# macOS 用 Homebrew
brew install deno
# 验证安装
deno --version
# deno 2.x.x (stable, release, x86_64-apple-darwin)
# v8 12.x.xxx
# typescript 5.x.x
Windows
# PowerShell(推荐)
irm https://deno.land/install.ps1 | iex
# winget
winget install DenoLand.Deno
# Scoop
scoop install deno
版本管理
# 升级到最新版
deno upgrade
# 升级到指定版本
deno upgrade --version 2.0.0
# 查看版本
deno --version
第一个 Deno 程序
无需 npm init,无需 package.json,直接创建 TypeScript 文件运行:
// hello.ts
const name: string = "Deno 2";
console.log(`你好,${name}!`);
// 使用 Web API fetch(无需安装任何库)
const res = await fetch("https://api.github.com/repos/denoland/deno");
const data = await res.json();
console.log(`Deno GitHub stars: ${data.stargazers_count}`);
# 运行(需要 --allow-net 权限访问网络)
deno run --allow-net hello.ts
注意权限:如果你忘记加 --allow-net 直接运行,Deno 会拒绝网络请求并报错:PermissionDenied: Requires net access to "api.github.com"。这正是 Deno 安全模型的体现——默认什么都不能做。
REPL 交互模式
# 启动 REPL
deno
# REPL 中支持顶层 await、TypeScript、Tab 补全
Deno 2.x.x
exit using ctrl+d, or close()
> const x: number = 42;
> x * 2
84
> await fetch("https://example.com").then(r => r.status)
200
名词解释:Deno 核心概念
-
权限系统
Deno 的安全沙盒机制。程序默认不能访问文件系统、网络、环境变量等系统资源。需要通过命令行标志(如
--allow-read)显式授予权限,或在 deno.json 中配置。这防止了恶意代码悄悄读取你的私钥文件或上传数据。 -
Web API 标准
Deno 直接实现 WHATWG/W3C 定义的 Web 标准 API,包括
fetch、URL、URLSearchParams、ReadableStream、SubtleCrypto、WebSocket等。这意味着在 Deno 中写的代码与浏览器代码极度相似,前后端逻辑可最大化复用。 -
JSR
JavaScript Registry(jsr.io),Deno 团队打造的新一代包注册表。与 npm 不同,JSR 原生支持 TypeScript(直接发布 TS 源码),使用 jsr: 前缀导入(如
import { assertEquals } from "jsr:@std/assert"),并支持多运行时(Deno/Node/Bun)。 -
Deno KV
Deno 内置的键值存储数据库,基于 SQLite(本地)或 FoundationDB(云端 Deno Deploy)。无需安装任何依赖,直接通过
Deno.openKv()使用,支持原子操作和 Watch 流,是边缘应用的理想轻量存储。 - Deno Deploy Deno 官方的边缘计算平台,全球 35+ 节点,代码运行在离用户最近的机房。支持 Playground 即时部署和 GitHub Actions 自动 CI/CD,底层基于 V8 Isolate 技术,冷启动极快(毫秒级)。
-
deno.json
Deno 的项目配置文件,类似 Node.js 的
package.json+tsconfig.json的合体。可配置 TypeScript 编译选项、import maps、任务脚本、权限、lint/fmt 规则等。完全可选——Deno 不依赖配置文件也能运行。
deno.json 配置文件快速上手
// deno.json — 项目根目录
{
"name": "my-deno-app",
"version": "1.0.0",
"tasks": {
"dev": "deno run --allow-net --allow-read --watch main.ts",
"start": "deno run --allow-net --allow-read main.ts",
"test": "deno test --allow-read"
},
"imports": {
"@std/assert": "jsr:@std/assert@^1.0.0",
"hono": "npm:hono@^4.0.0"
},
"compilerOptions": {
"strict": true,
"lib": ["deno.window"]
}
}
# 运行任务(类似 npm run dev)
deno task dev
# 运行测试
deno task test
本章小结:Deno 2 是 Node.js 原作者 Ryan Dahl 对自己设计失误的修正。核心哲学三板斧:安全默认(沙盒权限系统)、Web 标准(最接近浏览器的 API)、TypeScript 原生(零配置运行 .ts 文件)。Deno 2 新增完整 npm 兼容、JSR 包注册表和 workspace 支持,终于具备了生产环境竞争力。