node vs deno关于 Deno 和 Node 的未来
如果 Node 是今天编写的,它会是什么样子?一个词:Deno。JS运行时内置了 Typescript,并简化了模块解析。最重要的是,它将安全性提升到了一个新的水平,并缩小了我们在后端和浏览器上编写 JavaScript 的方式之间的差距。
不久前……
Node.js 于 2009 年发布,并以惊人的速度席卷全球。尽管最初人们对在后端运行 JavaScript 心存疑虑,但社区的支持无与伦比。很快,各种复杂的工具应运而生,几年后(2014 年),微软发布了 TypeScript,再次押注于 JavaScript。
如今,Node 是后端开发最流行的选择之一。基于事件的服务器理念确保了极高的性能/吞吐量比。运行 JavaScript 使其成为许多开发人员都能轻松上手的工具。从某种程度上来说,Node 通过降低入门门槛实现了后端开发的大众化。过去五年来,我一直愉快地使用 Node,但与此同时,我也对未来充满好奇。
新来者:Deno
Deno 项目于 2018 年启动,正如其网站所述,它为 JavaScript 和 Typescript 提供了安全的运行时。它主要由两部分组成:Typescript 前端和 Rust 后端。两者之间的通信通过 进行消息传递TypedArrays
。
Deno 是一个 JavaScript/TypeScript 运行时,具有安全的默认设置和出色的开发者体验。—— Deno 网站
在底层,我们找到了 Typescript 编译器、V8 引擎和 Tokio 事件循环的快照版本。所有这些,都以小于 10 MB 的二进制文件或 Rust crate 的形式提供。
老化的API
早在 2010 年,Node 就移除了 Promise,这在早期阶段对社区有所帮助。但随着 JavaScript 的发展越来越快,并引入了 await 和 async 功能,Node 的 API 开始老化。
如今,我们付出了巨大的努力来提升它们的速度,并同时保持版本控制的一致性。许多 API 调用仍然必须像promisify
使用语法一样包装在Promise
构造函数中。这一额外步骤增加了开发开销,并增加了应用程序中的样板代码。
相比之下,Promises 是 Deno 原生的异步行为绑定。Rust 后端使用 Rust Futures 镜像从 Typescript 前端接收到的 Promise 对象。Deno 中的异步操作总是返回一个Promise
。
Node 的另一个显著特点是它依赖Buffer
对象来读写数据。为了与浏览器界面保持一致,Deno 在TypedArrays
所有情况下都使用了对象。使用相同的数据结构,在后端和前端之间读写文件时保持一致性会容易得多。
零设置 Typescript
如果您使用 Typescript,您就会知道它是一款非凡的工具。它引入了一种可以随着应用程序的增长而强制执行的类型系统。这通过提供灵活性降低了传统静态类型的开销。项目可以在开始时进行部分类型设置,并且类型覆盖范围可以随着应用程序的增长而扩展。
在 Node 中,Typescript 可以直接与 一起使用ts-node
,但在生产环境中必须谨慎使用。最安全、性能最高的选择是用于ts-node
开发环境。然后将其编译为 JavaScript 进行生产环境。开发环境的设置可能比较复杂,尤其是与热代码重载等其他功能一起使用时。
另一方面,Deno 完全基于 Typescript。它使用编译器的快照版本,并捕获未更改的文件。您想运行 Typescript 代码吗?只需运行 Deno 二进制文件即可。无需配置,轻松便捷。就是这么简单,当然它也支持 JavaScript。
类似浏览器的包解析
Node 当前的解析方案使模块解析过于复杂。该算法在文件位置和命名方面提供了灵活性,但同时也牺牲了相当大的复杂性。
调用会首先搜索具有相同名称且扩展名为、或 的require
文件。如果指定的路径不包含以、或开头的节点,则假定该模块是核心模块或文件夹中的依赖项。如果名称不匹配,核心模块节点将检查该位置的 node_modules。如果未找到任何内容,它将前往父目录并继续执行此操作,直到到达文件系统的根目录。.js
.json
.node
'/'
'./'
'../'
node_modules
此外,文件夹可以指定为package.json
文件中的模块。该require
函数还能识别package.json
文件夹中所有已检查文件。一旦找到文件夹,Node 就会在其中查找index.js
文件index.node
。无需提供文件扩展名和灵活性带来的自由度,package.json
也显著增加了复杂性并降低了性能。
Deno 通过提供两种类型的模块解析(相对和基于 URL)来简化算法:
import * from "https://deno.land/std/testing/asserts.ts";
此外,解析算法不使用package.json
文件或node_modules
文件夹,而是require
使用 ES 模块导入。这使我们能够使用现代方法进行代码管理,而无需预编译器,并使我们再次更接近 JavaScript 在浏览器中的使用方式。
分布式包管理
目前,无服务器架构的采用率每年都在翻番。开发人员过去常常将单体应用拆分成微服务。现在,我们正在将微服务拆分成函数。为什么呢?一方面,除非迫不得已,否则没人愿意处理编排。另一方面,分布式系统更加灵活,可以更快地进行更改。归根结底,应用程序正在变成由更小、更独立的部分组成的系统。
一个典型的 JavaScript 后端应用程序只占代码总量的 0.3%。其余部分由文件夹中的包组成node_modules
。其中许多包在运行时几乎不使用。同时,整个生态系统依赖于一个集中式包管理器:npm
。
Deno为包管理带来了分布式方法。包可以通过 URL 解析,之后再进行捕获。应用程序变得更轻量,并且不再依赖单一的集中式包仓库。
关于安全
在进行后端开发时,我希望安全性能够做到开箱即用。我最不想考虑的就是 Linter 文件或 Node 模块访问网络或文件系统。
在 Deno 中,内部函数无法像在 Node 中那样随意调用 V8 API。Deno 的 API 与 JS 引擎之间的通信是通过基于类型数组的消息传递进行集中统一的。
除非特别允许,否则脚本不能访问文件、环境或网络。 — deno.land
使用 Deno 执行的脚本只有在用户明确指定的情况下才能访问文件系统和网络。更棒的是,可以使用 —allow 标志在文件、文件夹级别或网络路径级别授予权限。这为开发人员提供了对运行时发生的读写操作的精细控制。
$ deno --allow-net https://deno.land/std/examples/echo_server.ts
与应用于依赖项的“信任”策略相比,默认的安全性有了显著提升npn
。使用 Deno,您可以放心地运行和开发应用程序,确保它们能够按预期运行。
总结
Deno就像 Node 现在构建的样子。它提高了安全性,简化了模块解析,并支持 Typescript。
在我撰写本文时,我们仍处于 0.33 版本,并且发展迅速。我确信您之所以会在这里,是因为他们在某种程度上使用了 Node 或 JavaScript。如果您和我一样,您可能很喜欢它。但正如人们所说,真正爱上某样东西意味着放手。
我期待看到 Deno 超越单纯的脚本运行时,并听到它在生产环境中的初步体验。只要开发人员不断突破自我,我们就能期待更快、更直接、更可靠的软件。
最初发表于bogdanned.com。
文章来源:https://dev.to/bogdanned/on-deno-and-the-future-of-node-1l0p