引言
2020 年 5 月 13 日,可能是前端开发史上又一个里程碑式的一天,因为一个名为 Deno 1.0 版本正式发布了。
那么问题来了,Deno 是什么?为什么说是里程碑?它和 Node 有什么关系?和我又有什么关系?
带着疑问,跟着我一起来初窥 Deno 1.0 的神秘面纱吧。
背景
Deno 是 Ryan Dahl 在 2017 年开始的一个项目。从那时候开始,就有不少人开始关注这个项目了,为什么?这要从 Ryan Dahl 这个人说起。
Ryan Dahl ,2009 年创造了现在火遍全球技术圈的 Node.js ,被誉为 Node 之父。但是遗憾的是,他后来把 Node 移交给了其他开发者,转而研究人工智能,不再过问了。直到后来他再回过头捡起 Node 的时候,才发现这个项目已经背离了他的初衷,有一些无法忽视的问题。
于是就有了这样一件事,在 2018年一次公开的演讲中,Ryan Dahl 发表了一次让人意外的演讲,演讲的主题是 “Design Mistakes in Node”,翻译为中文则是“Node 的设计失误”,基本上把 Node 全部否定了,包括安全性、构建系统、package.json、node_modules、index.js 等等,并表示 Node 存在的种种不足导致有许多严重 bug 问题且不可回避。

由于上面这些原因,Ryan Dahl 决定放弃 Node,从头写一个替代品,彻底解决这些问题,那便是 Deno。
《Design Mistakes in Node》PPT:https://tinyclouds.org/jsconf2018.pdf
什么是Deno
Deno 目前有两种发音,"德诺"和"蒂诺"。之前看了阮一峰老师一篇关于 Deno 的文章之后,倾向于"蒂诺"这个发音。
Deno 的标志是一只恐龙,恐龙(dinosaur)的英文缩写正是 dino。 ——摘自《Deno 运行时入门教程:Node.js 的替代品》
Deno 这个名字取得就很有趣了,细心的朋友可能会发现,Deno这个名字就是来自 Node 的字母重新组合(Node = no + de),它的意思是"消灭 Node.js"(de = destroy, no = Node.js)。另外一种解释是颠倒 Node 字母的寓意就是说要颠覆 Node ,这两种意思其实也差不多。
实现
Node 的开发语言是 C++,而 Deno 却不一样。Deno 的开发一开始使用的是 Go 语言,后来换成了 Rust。
或许你会有疑问,为啥不是 C++、Go,为什么是 Rust ?
主要原因是 Rust 提供了很多现成的模块,对 Deno 项目来说,可以节约很多开发时间。如果使用 C++,就意味着一切东西都需要从头开始构建,这样的话就太浪费时间了。
优势
- Deno 基于最新的 JavaScript 语言;
- Deno 具有覆盖面广泛的标准库;
- Deno 以 TypeScript 为核心,配以更多独特的方式从而带来了巨大的优势,其中包括一流的 TypeScript 支持(Deno 自动编译 TypeScript 而无需你单独编译);
- Deno 大力拥抱 ES 模块标准;
- Deno 没有包管理器;
- Deno 具有一流的
await
语法支持; - Deno 内置测试工具;
- Deno 旨在尽可能地与浏览器兼容,例如通过提供内置对象
fetch
和全局window
对象
劣势
有一种“家庭背景”叫做生态,就凭这一点,目前的 Deno 完全是望尘莫及。很多优秀的东西没有流行起来,不是说它不够优秀,而是缺乏相关的生态。就像华为想搞自己的鸿蒙系统,即使真的能比安卓优秀,但是安卓巨大的生态就足够领先很多年。生态这东西不是一两年就能搞起来的,需要长年累月的维护、开发以及拓展。
Ryan Dahl 也说了,Deno 现在不打算对 Node 做兼容处理,也就是说很多东西在 Node 能用但是在 Deno 上用不了。所以对于 Deno 来说,还有很长的路要走。
Deno VS Node
Deno | Node | |
---|---|---|
版本 | v1.0.2 | v14.3.0 |
github star | 61.1k | 70.5k |
API 引用方式 | 全局对象 | 模块导入 |
模块系统 | ES Module 浏览器实现 | CommonJS & 新版 node 实验性 ES Module |
安全 | 默认安全 | 无安全限制 |
Typescript | 原生支持 | 第三方,如通过 ts-node 支持 |
包管理 | 原生支持 | npm + node_modules |
异步操作 | Promise | 回调 |
包分发 | 去中心化 import url | 中心化 npmjs.com |
入口 | import url 直接引入 | package.json 配置 |
打包、测试、格式化 | 原生支持 | 第三方如 eslint、gulp、webpack、babel 等 |
API 引用方式
Node 内置 API 通过模块导入的方式引用,例如:
const fs = require("fs");
fs.readFileSync("./node.txt");
而 Deno 则是一个全局对象 Deno
的属性和方法:
Deno.readFileSync("./deno.txt");
模块系统
Node 采用的是 CommonJS 规范,而 Deno 则是采用的 ES Module 的浏览器实现。
对于 Deno 来说:
// 支持
import * as fs from "https://deno.land/std/fs/mod.ts";
import { deepCopy } from "./deepCopy.js";
import foo from "/foo.ts";
// 不支持
import foo from "foo.ts";
import bar from "./bar"; // 必须指定扩展名
安全
Deno 默认安全,通过权限控制提供了一个安全的沙箱环境,程序只能访问由用户设置为可执行标志的文件。外部代码没有文件系统、网络、环境的访问权限,除非显式开启。而 Node 程序可以直接访问用户足以访问的任何内容。
支持 Typescript
Deno 支持开箱即用的 TypeScript 的环境,不需要任何配置文件就能在 Deno 中轻易地使用 TypeScript 。
包管理
Node 有一个官方的软件包管理器,称为 NPM。Deno 没有,而是允许你从 URL 导入任何 ES 模块。这使得 Deno 非常灵活,我们可以直接创建软件包而无需在 NPM 这样的存储库中发布它们。 Deno 下载模块以后,依然会有一个总的目录,在本地缓存模块,因此可以离线使用。
// index.js
import { white, bgRed } from "https://deno.land/std/fmt/colors.ts";
console.log(bgRed(white("hello world!")));
> deno run index.js
Download https://deno.land/std/fmt/colors.ts
Compile https://deno.land/std/fmt/colors.ts
hello world!
异步操作
Node 用回调的方式处理异步操作,而 Deno 则采用 Promise。
包分发
对于 www.npmjs.com 我们肯定都不陌生,它是推动 Node 蓬勃发展的重要支点。而 Deno 并没有一个像 npmjs.com 的仓库,通过 import url 的方式将互联网任何一处的代码都可以引用。
入口
我们知道 npm 包必须有 package.json
文件,里面不仅需要指明 main
或 module
或 browser
等字段来标明入口文件,还需要指明 name
、license
、description
等字段来说明这个包。在 Deno 中,其模块不需要任何配置文件,直接是 import url 的形式。
打包、测试、格式化
使用过 Node 的一定有这样的体会,我们需要经常引入一些其他工具或者插件,例如用 eslint 做代码格式校检、用 webpack 打包和构建项目、用 babel 做转化等等。而 Deno 通过内置了一些类似的工具,不需要我们再额外去引入,给我们的开发带来了不少的方便。
Deno 有一个内置的测试器,可以用来测试 JavaScript 或 TypeScript 代码。
Deno.test("hello world", () => {
const x = 1 + 2;
if (x !== 3) {
throw Error("x should be equal to 3");
}
});
Deno 有着内置的格式化工具,能够格式化 TypeScript 和 JavaScript 代码。
// 格式化当前目录和子目录下的所有 JS/TS 文件
deno fmt
// 格式化特定的文件
deno fmt myfile1.ts myfile2.ts
// 检查当前目录和子目录下的所有 JS/TS 文件是否都已被格式化
deno fmt --check
Deno 内置了调试器,使用 Chrome Devtools 或其他支持该协议的客户端(比如 VSCode)能够调试 Deno 程序。除此之外,还有打包器、脚本安装器、依赖查看器等等。
小结
在 Ryan Dahl 的计划中,他并不会去预想 Deno 在短时间内能够发展成一个多大规模的平台。当然咯,把时间调回2009年,JavaScript 还是人人都能取笑的一个有些怪异的小语言,谁也没想到如今 JavaScript 成为了使用最广泛的开发语言之一。
虽然 Deno 是以 Destroy-Node 为己任而开发的,但就目前来讲,Deno 取代 Node 是不可能的,Node 的占有率太高了,生态也足够完善,而 Deno 目前仅仅处于发展的最初期。不过我相信,凭借着它与生俱来的设计优势,以及目前的关注度,随着其相关生态的建设,将来的 Deno 会比 Node 更具优势。
如果你对 Deno 未来的发展也感兴趣的话,那就去给它个 star 吧。
最后附上 Deno 传送门:https://github.com/denoland/deno