译者 | 布加迪
审校 | 孙淑娟
您在本文中将了解Node.js和Deno、CommonJS与ECMAScript模块之间的区别、将TypeScript与Deno结合使用,以及使用Deno Deploy进行更快的部署。末尾附有注释,帮助您决定下一个开发项目使用Node.js还是Deno。
Node.js简介
Node.js是跨平台的JavaScript运行时环境,对服务器应用程序和桌面应用程序都很有用。它运行向系统注册的单线程事件循环来处理连接,每个新连接都会触发JavaScript回调函数。回调函数可以使用非阻塞I/O调用处理请求。若有必要,它可以从池中生成线程,以执行阻塞型或CPU密集型操作,并在CPU核心之间平衡负载。
大多数竞争性架构使用线程进行扩展,包括Apache HTTP Server、各种Java应用服务器、IIS和ASP.NET以及Ruby on Rails。相比之下,Node使用回调函数进行扩展,这种方法只需较少的内存就能处理更多的连接。
Node应用程序并不仅限于纯粹的JavaScript。您可以使用任何转译成JavaScript的语言,比如TypeScript和CoffeeScript。Node.js包含Google Chrome V8 JavaScript引擎,该引擎支持ECMAScript 2015 (ES6) 语法,根本不需要Babel之类的ES6-to-ES5转译器。
Node的用途主要来自其庞大的软件包库,该库可通过npm命令来访问。NPM的全称是Node软件包管理器,是标准Node.js安装系统的一部分,不过它有自己的网站。
基于JavaScript的Node.js平台由Ryan Dahl于2009年推出。当初开发这个更具可扩展性的平台是为了替代面向Linux和MacOS的Apache HTTP Server。NPM由Isaac Schlueter编写,于2010年推出。Node.js的原生Windows版本于2011年首次亮相。
Deno简介
Deno是面向JavaScript和TypeScript的安全运行时环境,已针对WebAssembly、JavaScript XML(JSX)及其TypeScript扩展TSX进行了扩展。Deno由Node.js的创建者开发,试图重新构思Node,充分利用自2009年以来JavaScript方面的进步,包括TypeScript编译器。
与Node.js一样,Deno本质上是Google V8 JavaScript引擎外面的外壳。与Node不同,它在其可执行映像中包含TypeScript编译器。创建了这两个运行时环境的Dahl曾表示,Node.js存在三个主要问题:基于集中式分发的设计欠佳的模块系统、必须支持的许多遗留API以及缺乏安全性。Deno全部解决了这三个问题。
Node的模块系统问题通过2022年年中的更新得到了解决。
CommonJS模块和ECMAScript模块
Node创建之时,JavaScript模块的事实标准是CommonJS,这是npm最初支持的。此后,ECMAScript委员会正式支持ECMAScript模块(又叫ES模块),它得到jspm软件包管理器的支持。Deno也支持ES模块。
对ES模块的实验性支持已添加在Node.js 12.12中,从Node.js 16版本成了稳定功能。 TypeScript 4.7也为Node.js 16支持ES模块。
在JavaScript中加载CommonJS模块的方法是使用require语句。加载ECMAScript模块的方法是使用import语句以及匹配的export语句。
最新的Node.js拥有CommonJS和ES模块的加载器。它们有何不同?CommonJS加载器是完全同步的,负责处理require()调用;支持文件夹作为模块;如果在require()调用中省略了扩展名(.js、.json或.node),可以尝试添加扩展名。CommonJS加载器不能用于加载ECMAScript模块。ES模块加载器则是异步的,负责处理import语句和import()表达式;不支持文件夹作为模块(必须完整指定目录索引,比如./startup/index.js);不搜索扩展名;并且只接受JavaScript文本文件的.js、.mjs和.cjs扩展名。ES模块可用于加载JavaScript CommonJS模块。
为什么Deno的安全性更高?
众所周知,Deno提高了Node.js的安全性。这主要是由于Deno在默认情况下不允许程序访问磁盘、网络、子进程或环境变量。如果您需要访问其中任何一项,可以使用命令行标志选择加入,这个标志的细粒度有多高就看您喜欢了,比如--allow-read=/tmp或--allow-net=google.com。Deno的另一个安全改进是,它总是一发现未捕获的错误就终结。相比之下,Node允许在未捕获的错误后继续执行,结果无法预测。
可以结合使用Node.js和Deno吗?
当您考虑是否将Node.js或Deno用于下一个服务器端JavaScript项目时,可能想知道是否可以结合使用两者。答案是“也许可以”。
首先,从Deno使用Node软件包往往是可行的。更棒的是,许多常见的阻碍有解决的方法。这包括使用Deno 标准库的std/node模块来“polyfill”Node的内置模块;使用CDN访问绝大多数npm软件包,并确保适用于Deno;使用导入图(import maps)。此外,从Deno1.15 开始,Deno拥有Node兼容模式。
缺点是,Node 的插件系统与Deno不兼容;Deno的Node兼容模式不支持TypeScript;几个内置的Node模块(比如vm)与Deno不兼容。
如果您是考虑换成Deno的Node用户,这里有一份速成表有所帮助。
将TypeScript与Deno一起使用
Deno将TypeScript视为头等语言,就像JavaScript或WebAssembly一样。它结合使用Deno中内置的TypeScript编译器和名为swc的Rust库,将TypeScript(以及TSX和JSX)转换成JavaScript。代码经过类型检查(如果启用检查)并转换后,存储在缓存中。换句话说,与Node.js或浏览器不同,您不需要使用tsc编译器手动为Deno转译TypeScript。
从Deno 1.23开始,默认情况下Deno中没有TypeScript类型检查。由于大多数开发人员通过编辑器与类型检查器进行交互,因此在Deno启动时再次进行类型检查没多大意义。话虽如此,您可以使用--check标志启用类型检查。
Deno Deploy实现更快的部署
Deno Deploy是一个分布式系统,允许您在全球各地靠近用户的地方(即边缘)运行JavaScript、TypeScript和WebAssembly。Deno Deploy服务器与V8运行时环境深度集成,提供最小的延迟,消除不必要的抽象。您可以使用Deno CLI在本地开发脚本,然后在不到一秒的时间内将其部署到Deno Deploy的托管基础架构,无需进行任何配置。
Deno Deploy建立在与Deno CLI相同的现代系统上,以全球可扩展的方式提供最新、最出色的Web技术:
- 在Web上构建:使用fetch、WebSocket或URL,就像在浏览器中一样。
- 对TypeScript和JSX的内置支持:类型安全的代码和直观的服务器端渲染,无需构建这一步。
- 与Web兼容的ECMAScript模块:像在浏览器中一样导入依赖项,无需显式安装。
- GitHub 集成:推送到分支,查看已部署的预览,并合并以发布到生产环境。
- 速度极快:不到一秒即可部署;服务全球,靠近用户。
•从URL来部署:仅使用URL即可部署代码。
Deno Deploy有两种版本。免费版仅限于每天100000个请求、每月100 GiB数据传输量以及每个请求10毫秒的CPU时间。专业版每月收费10美元,包括每月500万次请求和100 GiB数据传输量,加上每月每多出1百万次请求就收费2美元,以及超过配额后每传输1 GiB 数据就收费0.30美元;专业版允许每个请求50毫秒的CPU时间。
选择哪一个:Node.js还是Deno?
如您所料,至于哪种技术更适合您的用例,答案取决于许多因素。我的结论是,如果您现有的Node.js部署没坏掉,别修复它。如果您打算用TypeScript编写一个新项目,我强烈建议考虑Deno。然而,如果您的TypeScript项目需要使用多个没有Deno同等软件包的 Node.js软件包,需要权衡Deno项目的可行性。从概念验证入手几乎必不可少:如果不尝试一下,很难预测您是否可以让某个Node.js软件包在Deno中工作。
原文标题:Deno vs. Node.js: Which is better?,作者:Martin Heller