到 2024 年,构建基于 JavaScript
的现代 API
相对简单。我们可以使用Express.js
等库并在几分钟内启动可用的 API
。但是,现在最具挑战性的部分是选择正确的 JavaScript
引擎。
目前主流的三个运行时是:
Node.js
deno
bun
那么,我们应该为下一个大型 JavaScript
项目选择什么?重要的是要了解每个运行时都有优点和缺点。因此,本文通过比较 Bun
、Node.js
和 Deno
的优点、缺陷等来探讨它们!
Node.js
是用于服务器端开发的最广泛使用的 JavaScript
运行时。
它运行在 Google Chrome
的 JavaScript V8
引擎之上,确保闪电般快速且高度可靠的性能。Node.js
最有益的方面之一是事件循环。
事件循环允许我们在单个线程上运行整个应用程序,而不会遇到任何阻塞。它能够智能地将异步阻塞操作转移到第三方库 — libuv
上,该库执行所有异步 I/O
操作,并让 Node.js
主线程在调用堆栈空闲时处理回调。此外,通过引入工作线程,开发人员现在能够启动独立的 JavaScript
运行时并模拟多线程和并行处理。
Node.js
通过非阻塞 I/O
和可扩展性提供更高的性能,并由事件驱动架构支持,使其非常适合用户群不断增长的实时数据密集型应用程序。Node.js
拥有一个充满活力的生态系统,拥有丰富的库和框架,为开发人员提供了一个全面的工具包,可以跨 Web
开发和实时应用程序进行高效编码。Node.js
拥有一个充满活力且充满活力的社区,可以转化为定期更新和改进以及广泛发布的模块,开发人员可以轻松地将这些模块合并到他们的项目中。Node.js
是单线程的,因此它不适合繁重的计算或需要 CPU
密集型的任务。不过通过引入worker
线程后,Node.js
能够执行 CPU
密集型操作,而不会遇到性能问题。Node.js
中的异步函数彼此嵌套得如此之深,以至于代码变得复杂且混乱。不过可以通过使用 Promises
和async/await
等解决方案来避免这种情况。
Deno
是一种新兴的 JavaScript
和 TypeScript
运行时,致力于解决 Node.js
的某些缺点。
Deno
默认优先考虑安全性。
这可确保我们的代码在没有适当许可的情况下无法访问文件或网络。它运行在 JavaScript V8
引擎之上,并使用Rust
进行设计,这意味着它的速度快如闪电!
此外,Deno
还通过合并内置实用程序(例如用于网络的 fetch
)来采用当前的 Web
标准,与浏览器处理 JavaScript
的方式保持一致,并提供更具凝聚力的编码体验。
Deno
在安全的沙箱环境中运行,需要明确的权限才能访问文件系统、网络和环境,从而降低漏洞风险。Deno
通过依赖项检查器和代码格式化等内置工具增强了开发人员工作流程,并提供原生 TypeScript
支持,使开发人员能够专注于编码而不是配置。URL
简化模块管理:Deno
通过利用 URL
直接从 Web
获取依赖项(无需包管理器)来简化模块管理,从而简化代码库中的模块解析。Node.js
生态系统成熟:Deno
作为 Node.js
的更新替代品,正在开发其生态系统,预计通过社区贡献实现增长。与 Node
强大的生态系统相比,开发人员目前看到的现成解决方案可能更少。Deno
正在不断发展,但其第三方库的选择并不像 Node.js
的宝库那么广泛。开发人员可能会发现自己处于前沿,有时需要利用可用资源发挥创意,甚至需要自己制作资源。Bun
是一个快速、一体化的工具包,用于运行、构建、测试和调试 JavaScript
和 TypeScript
,从单个文件到全栈应用程序。
而且,有了 Bun
,我们所要做的就是立即开始使用。例如,我们不再需要安装诸如nodemon
、dot-env
之类的工具,因为 Bun
能够开箱即用地在开发人员模式下热重载,同时在默认情况下也会处理.env
文件。
此外,它还提供内置的 websocket
服务器,并使用自己的包管理器 - bunx
(比 NPM
快五倍)。但是,这还不是全部。Bun
不仅仅是一个 JavaScript
运行时。它是一个一体化工具包。这意味着它提供:
因此,我们无需花费时间配置项目,也无需维护复杂的样板项目。相反,我们可以启动一个 Bun
项目并立即开始!
Bun
是一个一体化工具包!这意味着我们不必花时间学习模块捆绑、配置测试框架。它默认执行此操作。这样我们就可以更快地开始!Bun
使用 JavaScriptCore
引擎,而 Node.js
、Deno
等运行时则使用 JavaScript V8
引擎。JavaScriptCore
引擎已针对更快的启动时间进行了优化,并且通常比两个运行时的性能更高。Bun
于几个月前推出。因此,它仍然没有一个成熟的问题社区。因此,如果我们严重依赖社区支持,则可能需要在继续之前检查是否有正确的支持。让我们来测试一下 Bun
、Deno
和 Nodejs
。
我们将用 JavaScript
编写一些需要大量内存的数学代码来处理大数据集。
考虑复杂的计算和大量的计算。
一个典型的例子是矩阵运算。这是一个矩阵乘法函数的示例:
function generateRandomMatrix(rows, cols) {
const matrix = [];
for (let i = 0; i < rows; i++) {
matrix[i] = [];
for (let j = 0; j < cols; j++) {
matrix[i][j] = Math.random();
}
}
return matrix;
}
function matrixMultiplication(a, b) {
const rowsA = a.length;
const colsA = a[0].length;
const rowsB = b.length;
const colsB = b[0].length;
if (colsA !== rowsB) {
throw new Error("矩阵不匹配");
}
const result = new Array(rowsA);
for (let i = 0; i < rowsA; i++) {
result[i] = new Array(colsB).fill(0);
}
for (let i = 0; i < rowsA; i++) {
for (let j = 0; j < colsB; j++) {
for (let k = 0; k < colsA; k++) {
result[i][j] += a[i][k] * b[k][j];
}
}
}
return result;
}
const matrixSize = 1000;
const matrixA = generateRandomMatrix(matrixSize, matrixSize);
const matrixB = generateRandomMatrix(matrixSize, matrixSize);
console.time("Matrix Multiplication");
const resultMatrix = matrixMultiplication(matrixA, matrixB);
console.timeEnd("Matrix Multiplication");
我们可以使用generateRandomMatrix
创建任意大小的随机矩阵。然后使用matrixMultiplication
将这些矩阵相乘。
随着矩阵大小(matrixSize
)的增加,我们会注意到内存使用量也会随之增加。让我们看看 Bun
、NodeJs
和 Deno
如何使用此代码执行操作。
我们将使用名为hyperfine
的基准测试工具。
hyperfine "bun index.js" "node index.js" "deno run index.js" --warmup=100 -i
上述 shell
命令将在不同的运行时执行上述代码,并且需要几分钟的时间才能提供基准测试结果。
Bun
在管理内存和 CPU
密集型任务方面的熟练程度不仅仅是巧合。它专为速度和最佳性能而设计。如果我们的项目需要快速和高效,Bun
被证明是一个绝佳的选择。
如果我们想构建一个能够在不牺牲功能的情况下提供速度和效率的应用程序,那么考虑 Bun
是一个值得的选择。
Node.js
:Node.js
拥有一个繁忙的社区。这反映了它在 API
开发中的长期存在和广泛接受。Deno
:Deno
正在迅速开拓自己的市场。它得到了一个充满活力、具有前瞻性思维、渴望突破界限和创新的社区的支持。Bun
:Bun
社区相比两者来说相对较小。这主要是因为它比两者更新。但是,根据 Bun
的发展方式,可以肯定地说,它很快就会拥有一个庞大的开发者社区!尽管 Bun
和 Deno
正在快速发展,但 Node.js
社区仍然难以超越。
Node.js
、Deno
和 Bun
都有独特的安全方法。下面简单介绍一下它们的区别:
Node.js
:它默认对我们的系统开放,具体取决于可能引入风险的第三方包。像npm audit
可以帮助捕获漏洞。例如:
npm audit
另外,使用以安全为中心的中间件helmet
可以增强 Node.js
应用程序的防御:
const helmet = require('helmet');
const app = require('express')();
app.use(helmet());
Deno
:它就像一个保险库,脚本被紧紧锁定,除非我们明确授予它们权限。运行具有有限访问权限的 Deno
服务器,如下所示:
deno run --allow-net=example.com server.js
Bun
:这个新事物的目标是速度并提供内置的安全功能。然而,它是最近出现的,因此它可能没有像其他方案一样经过那么多安全场景的测试。
显然,Deno
采取了高度宽松的方法。它对应用程序拥有的权限持谨慎态度。它以安全性为首要任务构建,在安全沙箱环境中运行,除非明确授权,否则限制文件和网络访问。
虽然 Node.js
和 Bun
合并了各自的安全措施,但 Deno
的附加内置安全层使其成为那些在 API
开发中优先考虑安全性的人的首选。
因此,如果安全性是我们的首要任务,请选择 Deno
!
没有绝对答案。这取决于我们的优先事项:
Node.js
:如果我们喜欢经过多年尝试和测试的稳定可靠的生态系统,那么这是首选运行时。Deno
。它还支持开箱即用的 Typescript
。Bun
:如果我们需要高速,尤其是在使用 JavaScript
或 TypeScript
时,此运行时应该是我们的首选。