Deno 简介
概念:一个安全的运行时的JavaScript和TypeScript语言环境;Deno是使用V8并内置于Rust的JavaScript和TypeScript的简单实现,现代化且安全的运行时。
特性:
- Deno 本身也是 Rust 的一个模块。如果你想在 Rust 里面使用 V8 引擎,就可以加载 Deno。它等于是一个 V8 的包装层,提供一些底层 API,让你跟 V8 引擎互动。
- Deno 只有一个可执行文件,所有操作都通过这个文件完成。它支持跨平台(Mac、Linux、Windows)。
- Deno 具有安全控制,默认情况下脚本不具有读写权限。如果脚本未授权,就读写文件系统或网络,会报错。
- Deno 支持 Web API,尽量跟浏览器保持一致。它提供 window 这个全局对象,同时支持 fetch、webCrypto、worker 等 Web 标准,也支持 onload、onunload、addEventListener 等事件操作函数。此外,Deno 所有的异步操作,一律返回 Promise。
- Deno 只支持 ES 模块,跟浏览器的模块加载规则一致。没有 npm,没有 npm_modules 目录,没有require()命令(即不支持 CommonJS 模块),也不需要package.json文件。所有模块通过 URL 加载,比如import { bar } from "https://foo.com/bar.ts"(绝对 URL)或import { bar } from './foo/bar.ts'(相对 URL)。因此,Deno 不需要一个中心化的模块储存系统,可以从任何地方加载模块。但是,Deno 下载模块以后,依然会有一个总的目录,在本地缓存模块,因此可以离线使用。
- Deno 原生支持 TypeScript 语言,可以直接运行,不必显式转码。它的内部会根据文件后缀名判断,如果是.ts后缀名,就先调用 TS 编译器,将其编译成 JavaScript;如果是.js后缀名,就直接传入 V8 引擎运行。
- Deno 内置了开发者需要的各种功能,不再需要外部工具。打包、格式清理、测试、安装、文档生成、linting、脚本编译成可执行文件等,都有专门命令。
Deno 历史及由来
Deno 是 Ryan Dahl 在2017年创立的。Ryan Dahl 也是 Node.js 的创始人,从2007年一直到2012年,他后来把 Node.js 移交给了其他开发者,不再过问了,转而研究人工智能。他始终不是很喜欢 Python 语言,久而久之,就想搞一个 JavaScript 语言的人工智能开发框架。等到他再回过头捡起 Node.js,发现这个项目已经背离了他的初衷,有一些无法忽视的问题。
首先,过去五六年,JavaScript 语言脱胎换骨,ES6 标准引入了大量新的语法特性。其中,影响最大的语法有两个:Promise 接口(以及 async 函数)和 ES 模块。Node.js 对这两个新语法的支持,都不理想。由于历史原因,Node.js 必须支持回调函数(callback),导致异步接口会有 Promise 和回调函数两种写法;同时,Node.js 自己的模块格式 CommonJS 与 ES 模块不兼容,导致迟迟无法完全支持 ES 模块。其次,Node.js 的模块管理工具 npm,逻辑越来越复杂;模块安装目录 npm_modules 极其庞杂,难以管理。Node.js 也几乎没有安全措施,用户只要下载了外部模块,就只好听任别人的代码在本地运行,进行各种读写操作。再次,Node.js 的功能也不完整,导致外部工具层出不穷,让开发者疲劳不堪:webpack,babel,typescript、eslint、prettier......
由于上面这些原因,Ryan Dahl 决定放弃 Node.js,从头写一个替代品,彻底解决这些问题。deno 这个名字就是来自 Node 的字母重新组合(Node = no + de),表示"拆除 Node.js"(de = destroy, no = Node.js)。跟 Node.js 一样,Deno 也是一个服务器运行时,但是支持多种语言,可以直接运行 JavaScript、TypeScript 和 WebAssembly 程序。它内置了 V8 引擎,用来解释 JavaScript。同时,也内置了 tsc 引擎,解释 TypeScript。它使用 Rust 语言开发,由于 Rust 原生支持 WebAssembly,所以它也能直接运行 WebAssembly。它的异步操作不使用 libuv 这个库,而是使用 Rust 语言的 Tokio 库,来实现事件循环(event loop)。
Deno 版本更新说明
Deno 1.0 发布了。Deno 是作者 Ryan Dahl 在 Node 之后的又一大作,它是一个新的运行时,用于在 Web 浏览器之外执行 JavaScript 和 TypeScript,其采用 Rust 编写而成(最初用的是 Golang)。
Deno 试图提供一个独立的工具来快速编写复杂功能的脚本,它将始终是单个可执行文件。就像 Web 浏览器一样,它知道如何获取外部代码。在 Deno 中,单个文件可以定义任意复杂的行为,而无需任何其它工具。
Ryan Dahl 认为过去他在设计 Node 时犯了一些错误,包括安全性、构建系统、package.json、node_modules、index.js 等等,并表示 Node 存在的种种不足导致有许多严重 bug 问题且不可回避,当前 JavaScript 和周围的软件基础架构已经发生了巨大的变化,值得进行简化,于是他重新设计了 Deno 这门脚本语言。
Rust API
今天正式发布的 1.0 版本带来了命令行界面 CLI 1.0。Deno 本身并不是一个单体的程序,而是设计为 Rust crate 的集合,以允许在不同的层进行集成。Deno 中的 Rust crate deno_core 不依赖于 TypeScript 或 Tokio,它只是提供了操作和资源基础架构。也就是说,它提供了一种将 Rust 特性绑定到 JavaScript promise 的有组织方式。CLI 则完全建立在 deno_core 之上。
rusty_v8 crate 提供高质量的 V8 C++ API 的 Rust 绑定。该 API 尝试尽可能与原始 C++ API 匹配,它是零成本的绑定,因为 Rust 中暴露的对象与在 C++ 中操作的对象完全相同。
HTTP 服务器性能
Deno 的 HTTP 服务器是采用 TypeScript 在原生 TCP socket 的顶层实现的,Node 的 HTTP 服务器使用 C 语言编写,并作为对 JavaScript 的高级绑定暴露。一直以来 Deno 拒绝将原生 HTTP 服务器绑定添加进来,因为这还需要优化 TCP socket 层,更常见的是优化 op 接口。
Deno 是一个合适的异步服务器,每秒 25k 请求足以满足大多数目的,此外,由于普遍使用 Promise,Deno 需要有更好的尾部延迟。目前 Deno HTTP 服务器每秒处理约 25 000 个请求,最大延迟为 1.3 毫秒,与之相比,Node 程序每秒处理 34 000 个请求,最大延迟介于 2 到 300 毫秒之间。
这样看来,作者认为 Deno 的 HTTP 服务器还有更多的性能优势,并表示希望在将来的版本中实现这一目标。具体关于 HTTP 服务器性能,可以查看:https://deno.land/benchmarks
插件/扩展
Deno 1.0 还带来了一个新生的插件系统,用于通过自定义操作扩展 Deno 运行时。但是,此接口仍在开发中,并已标记为不稳定。
此外,发布公告中还提及 Deno 稳定性与兼容性等内容,还介绍了接下来将会把 TSC 移植到 Rust,最终加速类型检查,提高从 TS 解析到 JS 性能的计划,详情查看:https://deno.land/v1