2023年为何 Deno 还没有干掉 Node.js?
大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!
阿特伍德定律(Atwood's Law)指出,任何可以用 JavaScript 编写的应用程序最终都将用 Javascript 编写。 这个预言是在 Node.js 诞生前两年提出的,结果证明也是非常正确的。 在浏览器上下文之外运行 JavaScript 环境的到来,鼓励开发者开始用纯 JS 编写服务器、CLI,甚至机器学习算法模型。
Any application that can be written in JS will eventually be written in JavaScript!
尽管 Node.js 是在服务器上运行 JavaScript 的事实标准,但并不是每个人都对它非常满意,尤其是它的作者!所以才有了其他的 JS Runtime,比如Deno等替代方案。以下是已发布文章的传送门:
《 JS Runtime vs. JS Engine!Deno/Node是运行时!》《 前有Deno、后有Bun、Node.js已穷途末路?》《 Node.js、Deno、Bun 6大典型场景性能大PK?》《 Node.js V20.0如期发布!盘点9大新特性! 》《 盘点全网最火的6 JavaScript 运行时!Node/Deno/Bun 在列! 》
毫无疑问,Node.js 目前是世界上最流行和使用最广泛的 JavaScript 运行时。 但是,Deno 在 2018 年的到来引起了巨大的轰动,开发人员可以使用具有现代功能的更安全的框架。
Deno 与 Node.js 由同一作者 Ryan Dahl 开发, Deno 被称为 Node.js 的继任者并修复了 Node.js 中一些主要设计缺陷。 尽管如此,Deno 的发布引发了很多关于 Deno 是否正在取代 Node.js 的猜测。 但是,到目前为止,好像一切都比较平和, Node.js 仍然是大多数开发人员的不二选择。
本文将尝试解释为什么开发者对 Deno 的采纳变得非常缓慢,以及为什么人们仍然更喜欢 Node.js,同时对 Node.js 和 Deno 做一个比较。
Node.js 是一个流行的服务器端、开源、跨平台的 JavaScript 运行时,它建立在谷歌的 V8 JS 引擎之上。 自 2009 年由 Ryan Dahl 发布 以来,Node.js 一直主导着 Web 开发世界。目前 Node.js 的最新版本是 V20.0.0。
Node.js 专注于事件驱动的 HTTP 服务器。 在处理请求时,它运行一个向系统注册的单线程事件循环,每个传入请求都会触发一个 JavaScript 回调函数。 回调函数能够使用非阻塞 I/O 的形式处理请求。
此外,Node.js 还可以生成线程来执行阻塞或 CPU 密集型任务,从而在 CPU 内核之间分配负载。 与大多数通过线程扩展的竞争框架不同,Node.js 基于回调函数的扩展机制可以以最少的内存使用来处理更多请求。
由于其异步 I/O 和事件驱动架构,Node.js 是轻量级的,非常适合可扩展、数据密集型、实时的 Web 应用程序,这些应用程序可以在分布式设备上运行。
比如在下面的 hello world 示例中,Node.js 可以同时处理多个连接。 每次连接时,都会触发回调,但如果没有工作要做,Node.js 就会休眠。
const http = require('http');
const hostname = '127.0.0.1';
const port = 3000;
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
// 输出hello world
res.end('Hello World');
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});
根据两个运行时的创建者 Ryan Dahl 的说法,Node.js 具有三个明显的缺点:
设计不当的模块系统依赖于集中分布(Centralized Distribution)不稳定的遗留 API缺乏安全性
而 Deno 解决了这三个问题并提供了更好的体验。
Deno(/diːnoʊ/,发音为 dee-no)是一个安全的 JavaScript、TypeScript 和 WebAssembly 运行时,同时具有出色的开发人员体验。 它建立在谷歌 JavaScript 运行时 V8、Rust 和 Tokio 之上。Deno 构建于以下几个核心能力:
语言:Deno 的核心是用 Rust 编写,而 Node 的核心是用 C 编写Tokio事件循环:是 Rust 编程语言的异步运行时, 它提供了编写网络应用程序所需的构建块,同时提供了针对各种系统的灵活性,从具有数十个内核的大型服务器到小型嵌入式设备。TypeScript 支持:Deno 开箱即用地支持 JavaScript 和 TypeScriptV8 引擎:Google 的 JavaScript 运行时,同时也用于 Chrome 和 Node 等
下表从语言支持(Deno 支持 TypeScript)、包管理(Node.js 使用 NPM)、安全&权限(Deno 支持沙箱)、代码集成(都是 V8 引擎)、机器执行(Deno 基于 Tokio 等 Rust 语言编写的底层能力)等诸多维度展示了 Node.js 和 Deno 的主要区别:
总之,Deno 构建于 Rust 之上,而 Node.js 构建于 C 之上。Deno 具有沙盒功能,更加安全,支持开箱即用的 TypeScript 和可靠的标准包集合,同时 Deno 也具有安全默认值,除非明确启用,否则无法访问文件、网络或其他环境。Deno 采用 Web 平台标准,始终与单个可执行文件一起分发,并具有内置的开发工具以提供高效、安全的运行时。
测试数据表明,在 HTTP 吞吐量、请求延迟等方面 Node.js 和 Deno 也是各有所长。
在下面的示例中,add 和 multiply 是 Deno 通过从远程模块导入并使用的示例:
/**
* remote.ts
*/
import {
add,
multiply,
} from "https://x.nest.land/[email protected]/source/index.js";
function totalCost(outbound: number, inbound: number, tax: number): number {
return multiply(add(outbound, inbound), tax);
}
console.log(totalCost(19, 31, 1.2));
console.log(totalCost(45, 27, 1.15));
/**
* Output
* 60
* 82.8
*/
接下来一起看看Deno、Node.js在几个关键维度的差异。
如上面的代码示例,借助 Deno开发人员可以直接从 URL 安装包,而无需像 npm 这样的集中式注册表。 尽管直接从 URL 下载包存在风险,例如:如果托管包的服务器遭到破坏,攻击者可能会修改代码包含恶意功能,但是 Deno 在一定程度上可以缓解这种问题。
总之,在 Deno中,没有包管理器的概念,外部模块直接导入到本地模块中。
这又带来了一个问题,即如何在没有包管理器的情况下管理远程依赖。在具有许多依赖性的大型项目中,如果将模块全部单独导入到单个模块中,则更新模块将变得很麻烦且耗时。
在 Deno 中解决此问题的标准做法是创建一个 deps.ts 文件。此文件中引用了所有必需的远程依赖关系,并且重新导出了所需的方法和类。本地模块从 deps.ts 导入所需方法和类,而不是远程依赖。
这样就可以轻松跨大型代码库更新模块,并解决“程序包管理器问题”(如果它存在的话)。开发依赖项也可以在单独的 dev_deps.ts 文件中进行管理。
/**
* deps.ts 从远程的 Ramda 模块中重新导出所需方法。
**/
export {
add,
multiply,
} from "https://x.nest.land/[email protected]/source/index.js";
而 Node.js 中借助于 npm 等包管理器很好的解决了此类问题。
Node.js 诞生于 JavaScript 中引入 Promises 或 async/await 之前。 因此,大多数 API 都被设计为接受错误优先的回调,这种方法经常会产生冗长而复杂的代码,比如下面的多层回调,又称为回调地狱。
login('john_d', (user) => {
getPosts(user.id, (posts) => {
getComments(posts[0].id, (comments) => {
getUser(comments[0].userId, (user) => {
console.log(user);
});
});
});
});
但是现在,Node.js 开发人员虽然可以使用 async/await 语法,还必须保证向后兼容, 因为API 经常更改且不稳定。
而 Deno 完全不同,不需要封装在 async 函数中,因为它已经使用 await 并支持最新的 JavaScript 功能。 因此,Deno 通过为开发人员简化此过程,促进将基于未来的 API 绑定到 JavaScript Promise 中。
Deno 还旨在与浏览器中运行的 JavaScript 代码使用的 Web 平台 API 兼容。 以符合标准的方式支持许多最流行的高级 Web API,例如 Fetch、Web Storage、Web Workers 和 Broadcast Channel 等等。
安全是 Ryan Dahl 创建 Deno 的主要原因之一。Deno 在禁止访问文件系统的安全沙箱环境中执行所有代码,除非明确请求授权。下面是未授权场景下的安全访问示例图:
Deno 的几个命令行标志可以在运行时使用,以启用脚本的特定功能。 默认情况下,这些功能处于非活动状态,除非明确开启:
— allow-env:允许访问环境变量— allow-hrtime:允许高分辨率时间测量— allow-net:允许网络访问— allow-read :允许读取文件系统— allow-write:允许文件系统写访问— allow-run:允许运行子进程
相比之下,Node.js 并非一个高度安全的框架。 例如:Node 不需要明确授予读取或写入文件系统的访问权限,但是它不是沙盒。
node.js v20引入了权限模型,但目前是一种实验性机制,用于在执行期间限制对特定资源的访问。主要包括: --allow-fs-read、--allow-fs-write 、--allow-child-process 、--allow-worker 、--experimental-permission 等等
因此,任何第三方库都可能引起诸多麻烦。 当然,有一些标准的安全措施可以防止对 Node.js 的跨站点请求伪造 (CSRF) 和跨站点脚本 (XSS) 等威胁。 这些机制涉及检查日志、正确管理错误和异常以及验证用户输入。
因此,尽管习惯了安全模块的严格性,但 Deno 总体来看是更安全环境的最佳选择。比如下面的代码,在Deno中运行默认保证安全。
import { Application } from "https://deno.land/x/abc/mod.ts";
const app = new Application();
app
.get("/", c => {
return `Hello, Abc! args: ${JSON.stringify(Deno.args)}`;
})
.start({ port: 8080 });
TypeScript 是 JavaScript 的超集,允许用户添加可选的静态类型。 Deno 通过使用带有缓存技术的 TypeScript 编译器来开箱即用的支持 TypeScript。 因此,Deno 可以编译、类型检查和执行代码,而无需将其转换为 JavaScript。
尽管 Node.js 缺乏像 Deno 那样固有的 TypeScript 支持,但由于 TypeScript 包的存在,TypeScript 已成为 Node.js 社区中一种众所周知且广泛使用的语言。 因此,TypeScript 和 Node 目前两者都能很好的集成工作。
如果开发者已经安装了 Node 和 npm,则只需运行如下命令:
npm install -g typescript
即可在机器上全局安装 TypeScript。 接下来,运行 tsc --init 来创建 TypeScript 配置文件。 然后可以使用 TypeScript 编译器 tsc 来编译 .ts 文件。下面是 tsconfig.json 的一个配置示例:
{
"compilerOptions": {
"module": "commonjs",
"noImplicitAny": true,
"removeComments": true,
"preserveConstEnums": true,
"sourceMap": true
},
"files": [
"core.ts",
//...更多文件配置
]
}
总之,如果开发者喜欢 TypeScript 并且更愿意尝试一种新颖的框架,那么 Deno 是合适的框架。 但是,在 Deno 中使用 TypeScript 进行开发不需要任何额外的配置。
自 ry 宣布在 Deno 两周年的 2020 年 5 月 13 日发布首个 Deno 1.0 正式版后,Deno 一直受到开发者们的持续关注。但是,这么多年过去了,为什么 Deno 还没有取代 Node?
当 Node.js 最初发布时,开发人员开始在实际项目中使用它。 多年来,为了满足开发社区的需求, Node.js 发生了很大的变化。 Node.js 现在是使用最广泛的 JavaScript 运行时,而 Deno、Bun 等相比之下只算是蹒跚学步阶段。
由于 Node.js 的广泛使用,社区、专业技术开发人员数量也迅速激增。 同时,Node.js 包系统基于 npm 构建,功能非常广泛且易于使用。 因此,当开发者主要关注灵活性和熟悉度时,Node.js 仍然是最佳选择。
然而,Node.js 并不完美, Deno 在 Node 落后的各个重要领域取得了重大进步,尤其是在安全性和标准合规性方面。 而且 Deno 的单一二进制模式使其比 Node.js 更具可移植性,而且其开放式模块架构可能会成为未来依赖导入的规范。
尽管 Deno 的社区很活跃,但相比 Node.js 仍然很小,特定解决方案的 Deno 包并不完善,而且 Node 兼容层也并非完美。
另一方面,Node.js 是高度模块化的, 其充分利用了包管理器 npm,可以使得开发者快速找到三方流行的库。借助于第三方库,可以在 Node.js 中实现 Deno 提供的许多功能。 因此,如果开发者只希望拥有 Deno 的部分功能,那么大多数情况下依然可以选择使用 Node.js ,尽管不如 Deno 般丝滑。
在 Node.js 中权限的易用性是另一个重要特性。 开发者可以在平台上快速收到反馈,无需经过各种授权。 Node.js 允许开发者使用最少的工作来快速编码,因为它很少依赖特定的权限。 这对于需要定期更新、大型专家团队的动态项目非常合适。
相比之下,Deno 仍处于学步段,其尚未在生产系统中经过全面测试,开发人员仍在适应这种新的运行时环境。 更多的开发者只是对 Deno 这种运行时保持好奇,或者持续关注。当然,Deno 具有巨大的前景,因为它解决了 Node.js 的重要缺点,包括:安全性、模块、回调和中央分发系统。
开发者有理由相信,随着 Deno 社区的逐步完善、壮大,Deno 逐渐会成为新的 Web 开发首选运行时。不过现阶段来看,大多数开发人员对 Node.js 的发展依然保持乐观,从而不会忙着迁移到其他运行时,比如 Deno、又比如 Bun。
本文主要大家介绍为什么2023年了,大多数开发者依然用 Node.js 而非 Deno。文章从什么是 Node.js 、什么是 Deno 、详细对比 Deno 与 Node 的区别 、为什么开发人员选择 Node 而不是 Deno等多个维度展开。
因为篇幅有限,文章并没有过多展开,如果有兴趣,文末的参考资料提供了优秀文档以供学习。最后,欢迎大家点赞、评论、转发、收藏!
https://github.com/tokio-rs/tokio-io
https://www.freecodecamp.org/news/what-is-node-js/
https://medium.com/deno-the-complete-reference/sandboxing-in-deno-b3d514d88b63
https://www.typescriptlang.org/docs/handbook/tsconfig-json.html
https://tokio.rs/tokio/tutorial
https://cult.honeypot.io/reads/deno-vs-node-main-differences/
https://externlabs.com/blogs/deno-vs-nodejs/
原文链接:https://cult.honeypot.io/reads/deno-vs-node-main-differences/
原文作者:Honeypot
翻译作者:头条《高级前端进阶》
科学家证实菩萨的存在,远距离感应证明万物皆有佛性
说起菩萨,相信很多人都是在《西游记》里见到过的,菩萨在人们的心目中就是非常慈悲的,所以很多人遇到了磨难就会求观世音菩萨保佑,那么菩萨真的存在吗?最近科学家证实菩萨的存在,引起了人们的震惊。下面一起来看看科学家证实菩萨的存在。一、科学家证实菩萨的存在我要新鲜事2017-12-05 12:30:370001人类是否已经完成最终进化?科学家这样认为(最终进化)
生物是永远不可能有进化的终点我们人类现在的进化步伐是非常慢的,根据很多古籍记载,人类像是从几千年之前到现在基本上都没有什么变化,就算是从几千年到现在,人类的生活方式和生活地带已经发生了非常大的改变,却依然都是如此,那是不是可以说明我们人类早就完成了终极进化,已经不需要再进化了呢,根据达尔文的生物进化论来说,不管是什么样的生物都是不可能会有进化的终点的,我们人类自然也是这样。我要新鲜事2023-05-15 02:53:590000世上罕见的小生物 你有见过吗
世上罕见的而又独特的生物,原来这个世界还有很多我们未知的生物、未知的秘密。小飞象章鱼,皮肤光滑,肌肉松软,它长着两只大象一样的耳朵,常年生活在400-4800米深海里。它仿佛一只可爱的小象游动在大海的深处。匹诺曹蛙长着一只可爱的长鼻子,它的鼻子在鸣叫时会翘起来朝上,闲下来时又会垂下。繁殖季节雄性蛙在呼叫雌性时,它的尖鼻子还会变大。我要新鲜事2017-12-05 12:29:330003从小米1到小米13,后摄布局不重样,那你觉得哪代强?
玩好手机,得要分析,大家好我是郁金香。咱认为,一个合格的手机厂商,如果不把后摄布局玩出花来,那都不算合格的手机厂商。[捂脸]今天咱们来一起追忆一下小米数字系列历代的后摄布局,机友们不防说出你心中后摄布局最上档次的一代或最掉档次的一代。[捂脸]图一小米1,后摄为长方形套圆形摄像头的居中布局,主摄800万像素。图二小米2,后摄为单独圆形摄像头的居中布局,主摄800万像素。我要新鲜事2023-05-13 21:33:370000印度地区遭遇百年里最热的夏天,发生了什么?(印度高温)
印度人在高温天气非常难以存活今年夏天有很多人都感受到了高温天气所带来的威胁,但也只是给我们的生活带来了一些不便而已,要知道在我国大多数人的生活还是比较幸福的,在很多地区人民的家里都是有着空调或者电风扇可以使用,就算是没有空调或者电风扇,他们也很有可能是住在山上,气候是自然的,比较凉爽,可是在我们隔壁的印度却没有过的这么舒服,甚至已经热死了很多人。印度的高温爆发我要新鲜事2023-05-15 08:17:060001