跳轉到

2018:Deno 構想——Ryan Dahl 對 Node 的反思#

事件#

2018年,Ryan Dahl 在 JSConf EU 發表著名演講 「我對 Node.js 感到後悔的10件事」,並宣布新專案 Deno。2020年5月發佈 Deno 1.0(見 2020-Deno-1-0問世)。

為何重要#

Dahl 指出 Node.js 的十大設計缺陷,Deno 逐一修正: 1. 模組系統:放棄 CommonJS 的 require,採用標準 ESM(import) 與 URL 匯入,不需要 node_modules。 2. TypeScript 一等公民:內建 TS 支援,不需建置設定。 3. 安全性:預設沙箱,檔案/網路/環境變數存取需明確授權(--allow-read 等)——Node 完全沒有權限模型。 4. Promise 而非回呼:Node 早期 API 以回呼為主(error-first callback),導致回呼地獄;Deno 全部使用 Promise 與 async/await。 5. 單一可執行檔、頂層 await、標準 API 對齊瀏覽器(如 fetch 內建)。

理論與實用原因#

  • 理論原因:以瀏覽器為「正確先例」——JavaScript 的正規模組與安全模型應以 Web 標準為準,伺服器端不應自成體系。
  • 實用原因:Node 的 node_modules 目錄暴脹、package.json 相依地獄、安全漏洞頻傳(npm 供應鏈攻擊),都需要根本性重設計。

彌補了什麼缺陷#

彌補了 Node.js「回呼式 API、無權限模型、非標準模組系統、TS 支援需外部工具」的歷史包袱。Deno 也證明了一件事:一個語言的運行時可以有多個競爭實作,隨後 Bun(2023)加入戰局,Node 本身也被迫向 ESM、fetch、權限模型靠攏。

相關條目#

程式範例#

1. Node 的設計缺陷 vs Deno 的修正#

// Node(2009):error-first callback——回呼地獄的根源
fs.readFile("config.json", (err, data) => {
  if (err) return cb(err);
  doSomething(data, cb);
});

// Deno(2018):全 Promise + async/await,不需回呼
const data = await Deno.readTextFile("config.json");
doSomething(data);

2. 安全模型:預設沙箱,Node 完全沒有權限概念#

# Node:程式碼隨便讀檔、上網、改環境變數——全開放
node script.js

# Deno:預設什麼都不能做,明確授權
deno run script.js                      # 💥 PermissionDenied
deno run --allow-read --allow-net script.js   # ✅ 明確授權
// script.js
const data = await Deno.readTextFile("./config.json");  // 需 --allow-read
const res = await fetch("https://api.example.com");     // 需 --allow-net

3. URL 匯入:不需要 node_modules 與中央 registry#

// Node:npm + node_modules 目錄
const express = require("express");

// Deno:直接從 URL 匯入,模組快取在本機
import { serve } from "https://deno.land/std@0.200.0/http/server.ts";
serve(() => new Response("Hello"));

4. TypeScript 開箱即用#

deno run server.ts     # 直接執行 .ts——Node 需要 tsc 編譯或 ts-node