【译】Deno是啥?会取代Node.js吗?

5,071 阅读6分钟

原文链接: blog.bitsrc.io/what-is-den…

Denonode.js 的作者 Ryan Dahl 编写的,这是否意味着 Deno 实际上就是 Node.js 的替代品,我们是否应该开始计划重构冲刺呢? 如果你想了解更多,请往下看。

在2018年,Ryan 进行了一次演讲,在演讲中他提出了他认为的有关 Node.js 的十大问题。在演讲结束时,他揭开了 Deno 的面纱。当时 Deno 只是他正在建设中的一个小项目,也许被大家称作 Node.js v2版本,在 Node.js 的基础上进行了改进,并且更加安全。

这里是演讲的视频地址,大家最好去看一看。

两年后,在2020年5月13日,官方正式发布了 Deno 1.0版本。一个全新的让 JavaScript 运行在服务端的开发平台。不像 Node.js 是用 C++ 语言开发,Deno 底层是用基于 Tokio 平台(提供 JavaScript 所需的异步运行环境)的 Rust 语言编写的,仍然运行在 V8 引擎上。

有什么新知识

我们不单单在谈论与当前 Node.js 完全兼容的新 JavaScript 运行环境,相反的是,RyanDeno 中增加了一些他认为在 Node.js 中所缺少的东西。

安全集成

默认情况下,Node.js 允许你访问任何内容,也就是说,你可以读写文件系统,发送传输请求,访问环境变量等等。 作为开发人员,具有这种访问权限当然是有好处的,但在编写代码时万一不小心,有可能会带来安全风险。

因此,Deno 可以使用命令行参数来启用或禁用对不同安全功能的访问。如果你需要脚本能够访问 /etc 文件夹,可以执行以下操作:

deno --allow-read=/etc myscript.ts

这样,你的代码就可以从该文件夹中读取任何内容,并且会在没有权限的情况下抛出全异常。 这类似于其他平台处理安全性的方式。如果你是 Android 用户,你肯定遇到过很多应用程序曾要求你允许它们读取联系人,电话,文件夹等,这与此类似。 通过在执行脚本的命令行中敲上这些参数,就可以提供代码所需的权限。

更完整的标准库

自从第一个 Node.js 版本以来,JavaScript 就开始改进其标准库。但是与其他语言相比,它还有很长的路要走。 Deno 也致力于改善这一点,并声称其拥有一个非常完整的标准库,允许开发人员使用官方工具来执行基本的任务,只有复杂的任务时才需要使用外部库(比如 NPM )。

本质上讲,Deno 提供了诸如 为终端文本添加颜色、使用外部数据结构(例如二进制,csvyaml 等)、生成 UUID 甚至编写 websocket 等开箱即用的方法。 还有一些其他的更基本的模块可用,例如访问文件系统,日期转换函数,http 相关函数等等。

集成Typescript

你没有看错,如果你是 TypeScript 的爱好者,那么 Deno 本身就可以满足你的需要,不需要额外引入外部库,默认情况下就可以将 Typescript 转换为 JavaScript

尽管默认情况下,Deno 自身会完成转换,但是你可以使用自己的 tsconfig.json 文件来覆盖默认配置:

deno run -c tsconfig.json [your-script.ts]

默认配置采用的是严格模式,因此任何不符合规范的编码都会立即得到警告。

不再需要 NPM 或node_modules 文件夹

Node.js 中, 每一个模块和它的祖先模块都有着千丝万缕的依赖关系。是否太臃肿了呢?是否是一个错误的方式来分发管理依赖呢?这绝对是 Node.js 最具争议的方面之一,因此 Deno 决定完全放弃它。

那么,Deno 是如何处理依赖关系的? 它允许你从任何地方引入模块。换句话说,你可以简单地执行以下操作:

import * as log from "https://deno.land/std/log/mod.ts";

从此不再需要拥有自己的集中式存储库,但是你必须谨慎的进行此操作,因为从无法控制的第三方来源导入模块会使你暴露。

实际上,我们也不再需要 package.json,现在通过在名为 deps.ts 的文件中维护模块列表及其各自的URL即可实现依赖管理。 但是版本控制怎么办呢?我知道你就会问。你可以在 URL 上指定软件包的版本,虽然不是很精美,但确管用。

一个简单的 deps.ts 文件也许是这样子的:

export { assert } from "https://deno.land/std@v0.39.0/testing/asserts.ts";
export { green, bold } from "https://deno.land/std@v0.39.0/fmt/colors.ts";

这将重新导出模块,如果你想更改其引用版本,简单的更改 URL 就可以了。

顺便说一下,第一次执行代码后,导入的模块就会被缓存下来直到你下一次重启。

还有啥

Deno 还包含其他功能,例如开箱即用的大型工具,包括 test runner, debugger, file watcher 等。 但是有些只是其提供的 API,需要在其基础上写自己的逻辑才能使用它们。

Deno.watchFs 提供的 file watcher API 为例,如果你正在寻找与 nodemon 类似的解决方案,你必须自己编写代码来实现。 下面的23行代码是一个解决这种问题的列子:

function startProcess(args: string[] = []): Deno.Process {
  return Deno.run({ cmd: ['deno', ...args] });
}

const throttle = 500;
let app: Deno.Process = startProcess(Deno.args);
let timeout: number|null = null;

function runApp() {
  app && app.close();
  app = startProcess(Deno.args);
}

for await (const event of Deno.watchFs('.')) {
  if (event.kind !== "access") {
    if (timeout) clearTimeout(timeout);
    timeout = setTimeout(runApp, throttle);
  }
}

会取代Node.js吗

我们中的有些人早在 Node.js 0.10 版本推出的那天起就已经开始使用它了,并且是在生产环境中使用它!真相听起来也许有点吓人,但是我们正在做,因为没有别的能替代的。 PHP,Python 甚至 Ruby(更不用说 Java.NET)都无法与具有 JavaScript 和异步I/O模型的 Node.js 相提并论。 多年来,Node(和JavaScript)已经发展到可以满足行业要求。 是不是很完美? 但是,就像生活中的任何其他事物一样,编程语言也不是完美无缺的。

Deno 现在只是一个仅有2年开发迭代的产品。它尚未在生产环境中进行尝试,也尚未编写异常的测试用例来了解其如何处理边界情况。直到做到了这一点,它才能供早期尝试者使用。也许一年后,我们将看到有些公司开始分享他们的使用经验,他们如何解决新发现的缺点等。最终,社区将对其进行调整让它变得更有用,更受众。它会取代 Node.js 吗?我们拭目以待。