Ryan Dahl 创造 nodejs 的大牛,去年花了一年半的时间在新的项目Deno上。Deno 是什么呢?一个被认为是修复完善 nodejs 内在问题的新的 JavaScript 运行时的工具。javascript
不要理解错了,在我本身看来 node 是一个很好的服务端 JavaScript 运行时工具,同时也由于它的生态系统的庞大和使用的语言是 JavaScript。然鹅,Dahl 也认可有一些东西在 node 里面是支持不多的——安全性、模块化、依赖性等等。java
在他的辩护中,他并无想到这个平台会在如此短的时间里增加这么快。此外,早在 2009 年,JavaScript 仍然是一种奇怪的小语言,每一个人都看不起,并且它的许多功能尚未。node
Deno 是一个基于 V8 引擎的安全的 Typescript 运行时工具(V8 是谷歌的 JavaScript 运行时引擎)。
它是由如下组成:webpack
- Rust——Deno 的核心是用 Rust 写的,就如同 nodejs 是用 c++写的同样。
- Tokio——Rust 编程语言的异步运行时,提供异步事件驱动平台,构建快速,可靠和轻量级网络应用。利用 Rust 的全部权和并发模型确保线程安全(用 Rust 写的事件循环)
- Typescript——Deno 支持 JavaScript 和 Typescript(开箱即用)
- V8——谷歌的 JavaScript 运行时引擎,被用在 Chrome 和 node 中
那咱们来看一下 Deno 提供了那些特性。c++
Deno 最重要的特性是聚焦在安全性上。
与 nodejs 相反,Deno 默认在沙箱中执行代码,它意味着运行时不能去作一些事情:git
一块儿看一下权限控制系统怎么工做的。web
(async () => {
const encoder = new TextEncoder();
const data = encoder.encode("Hello world\n");
await Deno.writeFile("hello.txt", data);
await Deno.writeFile("hello2.txt", data);
})();
复制代码
这个脚本创造了两个文本文件,叫作 hello.txt 和 hello2.txt,里面的内容都是Hello word
文本。当这个代码在沙箱中开始执行的时候,它是没有权限访问文件系统的。typescript
这个也要注意。咱们使用的是 Deno 命名空间,而不是 fs 模块,也正如咱们在 nodejs 中,Deno 的命名空间提供了许多基础辅助函数。经过使用命名空间,也会失去浏览器兼容性,这个咱们后面讨论。npm
当咱们执行如下命令时:编程
deno run write-hello.ts
复制代码
咱们会看到以下提示:
⚠️Deno requests write access to "/Users/user/folder/hello.txt". Grant? [a/y/n/d (a = allow always, y = allow once, n = deny once, d = deny always)]
复制代码
咱们在每次调用沙箱的时候都会收到权限控制的提示,固然若是咱们选择了allow always
选项,那就只会提示一次。
若是咱们选择了deny
选项,这个PermissionDenied
的错误将会抛出,这个进程将会终止退出,由于咱们没有任何的容错处理。
若是咱们执行脚本的时候使用一下命令:
deno run --allow-write write-hello.ts
复制代码
将不会有提示,而后两个文本文件会被建立。
这个--allow-write
标识是对于文件系统可用的,这儿也有--allow-net
、--allow-env
、--allow-run
,它们的做用是容许网络请求、容许访问环境变量、容许运行子进程。
Deno 和浏览器同样,加载模块是经过 URL 的,许多朋友他们第一次看见在服务端经过引入 URL 来加载模块是感到困惑的,可是这个模式也是说的通的——一块儿来看看:
import { assertEquals } from "https://deno.land/std/testing/asserts.ts";
复制代码
经过 URL 引入报有什么好处,你可能会这么说。这个答案是简单的:经过 URL,Deno 的包能够不是集中的汇集在一个中心仓库,好比npm
。不久前就发生了一些事情,这里就不详细阐述了。
经过 URL 引入代码,咱们可让包的建立者把代码托管到他们本身想托管的地方——去中心化。 没有多余的 package.json 和 node_modules。
当咱们开始运行一个 Deno 的程序时,他会下载全部的依赖包,而且缓存他们,一旦它们缓存到了本地,Deno 就不会再下载他们了,除非你在运行的时候加上--reload
符号标识。
这儿有一些比较重要的问题:
因为它再也不是中心仓库来管理,存包的网站可能由于一些缘由崩了。对于正在开发的项目,这是一个很糟糕的状况,对于已经上线的项目,这更是毁灭性的打击。
正如咱们前面提到的,Deno 会缓存模块包,因为缓存是存在咱们的本地的硬盘上的,Deno 的建立者建议在咱们的版本控制系统(即 git)中检查它并将其保存在存储库中。这样,即便网站崩了,开发者仍然保留了下载的版本。
Deno 将缓存存储在$DENO_DIR
环境变量下指定的目录中。若是咱们不本身设置变量,它将被设置为系统的默认缓存目录。咱们能够在咱们的本地存储库中的某处设置$DENO_DIR
并将其检入版本控制系统。
老是经过 URL 来引入文件,可能会变得特别复杂或者说麻烦,比较好的是,Deno 目前有两个选项提供给咱们。
第一个选项是从本地文件从新导出导入的模块,像这样:
export { test, assertEquals } from "https://deno.land/std/testing/mod.ts";
复制代码
咱们给上面这个文件命名为local-test-utils.ts
,如今,若是咱们想再次使用test
或者assertEquals
函数方法,咱们仅仅像这样引入就能够了:
import { test, assertEquals } from "./local-test-utils.ts";
复制代码
因此这不是一个大问题,不论是否使用的是 URL 引入的。
第二个选项是建立一个引入地图文件,更具体地说是一个 JSON 文件:
{
"imports": {
"http/": "https://deno.land/std/http/"
}
}
复制代码
引入的时候,这么引入:
import { serve } from "http/server.ts";
复制代码
为了它可以工做,咱们必须经过--importmap
标识告诉 Deno 引入地图文件是什么:
deno run --importmap=import_map.json hello_server.ts
复制代码
版本必须被包的提供者支持,但从客户端来看,它只是在 URL 中设置版本号,以下所示:
https://unpkg.com/liltest@0.0.5/dist/liltest.js
。
Deno 旨在与浏览器兼容。从技术上讲,在使用 ES 模块时,咱们没必要再使用任何构建工具(如 webpack 来使咱们的应用程序能够在浏览器中使用)。
可是,像 Babel 这样的工具会将代码转换为 ES5 版本的 JavaScript,所以,即便在不支持该语言全部最新功能的旧版浏览器中,代码也能够运行。但这也是以在最终文件中包含大量没必要要的代码并使输出文件膨胀为代价的。
由咱们决定咱们的主要目标是什么,并相应地作出选择。
Deno 使得无需任何配置文件便可轻松使用 TypeScript。固然仍然也能够用纯 JavaScript 编写程序并使用 Deno 执行它们而不会有任何麻烦。
Deno 是 TypeScript 和 JavaScript 的新运行时,是一个有趣的项目,如今已经稳定增加了很长一段时间。可是在它被认为是生产就绪以前还有很长的路要走。
因为它的去中心化特色,它须要从集中式软件包注册表(即 npm)中释放 JavaScript 生态系统。
Dahl 表示他但愿在夏季结束前发布 1.0 版本,因此若是你对 Deno 的将来发展感兴趣,那么就 star 它吧。